/****************************************************************************/
/*
* API for api parse xml rom to ram & store xml ram to rom.
*/
/****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>	/*for ntohl*/
#include <sys/time.h>
#include <sys/stat.h>
#include "cms_common.h"
#include "libmdm.h"
#include "cms_mdm.h"
#include "pdm.h"
#include "xmlparse.h"
#include "xml_parse_lib.h"
#include "cms_log.h"
#ifdef SYSDEF_PARSER_ON_HOST 
#include "cms_xmlToShm.h"
#endif

cmsXmlCb_t	*pdmCB;

#ifdef SYSDEF_PARSER_ON_HOST
static int cmsXml_NodeAddObject(objectNode_t *node, parameterList_t *list);
#endif
int cmsXml_ParseIndexNode(FILE *file, objectNode_t *node, objectNode_t **tempPtr, indexNodeFlagList_t *indexNodeFlagPtr);
int cmsXml_ParseNodeToBuf(FILE *file, objectNode_t *node, indexNodeFlagList_t *indexNodeFlagPtr);

tagNode_t *tagPool;
static int errorflag=0;
static int nodeNum = 0;
static int checkNode = 0;
static XML_Parser parser;
#ifdef SYSDEF_PARSER_ON_HOST 
static int indexChildNumCheck = 0;	/*if node is index node, use to check MAXNODENUMBER is 0 or not*/
static int skipIndexChild = 0;		/*if 1, the node is index child and node number is 0, skip it*/
#ifdef CMS_XML_PARSE_PHASE_1
static int filterXmlFlag = 0;			/*Doing CMS_XML_PHASE_1 flag, 1 if filter.xml is not empty.*/
Xml_object *fCurrent = 0;			/*point to current node in XML Filter file.*/
Xml_object *rootFilter = NULL;		/*point to the root of XML Filter file.*/
#endif
#else
static int fileSpaceDepth = 0;
#endif

#ifdef SYSDEF_PARSER_ON_HOST /* compile time. */
static uint64_t indexChildDepth = 0;
unsigned long long HTONLL( unsigned long long src );
unsigned long long NTOHLL( unsigned long long src );
void printIAArray( uint64_t value );
uint64_t cmsXmlSetIAValue( uint64_t originalValue, int index, uint64_t setValue );
int compareIAByDepth( uint64_t a, uint64_t b, uint8_t depth );
void cmsXml_SetPreObjIA( cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset, uint64_t valueIA );
void cmsXml_SetPreObjNext( cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset, cmsoffset_t valueOffset );
void cmsXml_SetPreObjAttr( cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset, uint32_t valueAttr );
cmsoffset_t cmsXmlAddObjectWithAssignIA( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset, uint64_t IA );

#else /* running time. */
static int pdmTmpOID = 0;
static uint64_t pdmTmpIA = 0;
#endif
static int skipParameter = 0;


enum parse_state{
	/* Common */
	StateUnknown=0,
	StateStart,
	StateDone,
	StateError,
	StateNodeNotExist,
	/* Base */
	StateConfig,

	/* Building the config tree for a module */
	StateSetting
};

const typeTable_t typeTable[] = {
	{PARAMETER_TYPE_UINT8,  "uint8"},
	{PARAMETER_TYPE_UINT16, "uint16"},
	{PARAMETER_TYPE_UINT32, "uint32"},
	{PARAMETER_TYPE_MAC, "mac"},
	{PARAMETER_TYPE_UINT64, "uint64"},
	{PARAMETER_TYPE_IPV6, "ipv6"},
	{PARAMETER_TYPE_DATETIME, "datetime"},
	{PARAMETER_TYPE_BOOLEAN, "boolean"},
	{PARAMETER_TYPE_IPV4, "ipv4"},
	{PARAMETER_TYPE_SINT7, "sint7"},
	{PARAMETER_TYPE_SINT15, "sint15"},
	{PARAMETER_TYPE_SINT31, "sint31"},
	{PARAMETER_TYPE_SINT63, "sint63"},
	{PARAMETER_TYPE_STRING, "string"},
	{0, "NULL"}
};

/*
	Description: 
		function used for free tagPool.
	Parameters:
			
	return:
	
*/
void free_tag_stack(void)
{
	struct tagNode_s *stackNode;
	while(tagPool){
		stackNode=tagPool;
		NODE_DEL(tagPool, stackNode);
		free(stackNode);
	}
	return;
}

/*
	Description: 
		function compares the two strings str1 and str2, ignoring the case of the characters.
	Parameters:
		str1:string1
		str2:string2
	return:
		0:equal
		1,-1: unequal
	
*/
int
stricmp(
    const char *str1,
    const char *str2
)
{
    char ch;
    int diff;
 
    if ( str1 == str2 ) {
        return 0;
    } else if ( str1 == NULL ) {
        return -1;
    } else if ( str2 == NULL ) {
        return 1;
    }

    while (  1  ) {
        diff = (ch = *str1) - *str2;
        if ( diff < 0 ) {
            if ( (diff != ('A'-'a')) || (ch < 'A') || (ch > 'Z') ) { 
                /* found difference */ 
                return -1;
            } 
            /* else matched with different letter case -> continue */
        } else if ( diff > 0 ) {
            if ( (diff != ('a'-'A')) || (ch < 'a') || (ch > 'z') ) {
                /* found difference */
                return 1;
            }
            /* else matched with different letter case -> continue */
        } else if ( ch == '\0' ) {
            /* end of str1 && end of str2 */
            break;
        } 
        /* else matched exactly -> continue */
        str1++;
        str2++;
    }
    return 0;
}

/*
	Description: 
		function used to check sysdef.xml Max/Min Value.
	Parameters:
		limitValue: Max or Min value.
		checkValue: The value need to be checked.
	return:
		0:CMS_OK
		-1: Out of range
	
*/
int maxAndMinValueCheck(char *limitValue,char *checkValue)
{
	char ch;
    	int diff = 0;
	while (  1  ) {
		diff = (ch = *checkValue) - *limitValue;
		if ( diff > 0 ) {
			return CMS_NOK;
		} else if ( ch == '\0' ) {
			break;
		} 
		checkValue++;
		limitValue++;
	}
	return 0;
}

/*
	Description: 
		function used to get attribute value from xml.
	Parameters:
		attrs: xml parser expat will give this attribute pointer.
		attrPtr: Attribute List structure.
	return:
		0:CMS_OK
		-1: error
	
*/
int cms_GetAttrValue(const char **attrs, attrList_t *attrPtr)
{
	char	*attr;
	char *value=NULL;
	int attrIndex = 0;
#ifdef SYSDEF_PARSER_ON_HOST
	typeTable_t *typePtr;
	int length = 0;
	int maxFlag = 0;
	int minFlag = 0;
#endif
	int notifyOff=1;//Check notification="off"
	int checkIfNode = 0; //Check this tag is parameter or node
	uint32_t attrtmp;

	attrPtr->priValue = 50;

	while(attrs){
		attr=(char*) attrs[attrIndex++];
		value=(char*) attrs[attrIndex++];
		if(!attr || !value)
			break;

		if(!stricmp(attr, "PARAMETER"))
		{
			attrPtr->paraFlag = 1;
			checkIfNode = 0;/*In case HIDEFROMACS for parameter is added before PARAMETER attribute*/
#ifdef SYSDEF_PARSER_ON_HOST			
			if(!stricmp(value, "configured")){
				attrPtr->configFlag = 1;
				attrPtr->attrValue |= PARAMETER_ATTR_CONFIG;
			}
			else if(!stricmp(value, "nonconfigured"))
				attrPtr->configFlag = 0;
			else
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: PARAMETER value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
#else
			if(!stricmp(value, "nonconfigured"))
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: PARAMETER value can't be \"nonconfigured\".\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
#endif			
		}
		else if(!stricmp(attr, "NOTIFICATION"))
		{
			notifyOff = 0;
			if(!stricmp(value, "active")){
				attrPtr->attrValue |= PARAMETER_ATTR_ACTIVENOTIFY;
				attrPtr->attrValue &=~PARAMETER_ATTR_PASSIVENOTIFY;
			}else if(!stricmp(value, "passive")){
				attrPtr->attrValue &=~PARAMETER_ATTR_ACTIVENOTIFY;
				attrPtr->attrValue |= PARAMETER_ATTR_PASSIVENOTIFY;
			}else if(!stricmp(value, "off")){
				attrPtr->attrValue &=~PARAMETER_ATTR_NOTIFY;
			}else if(!stricmp(value, "unsupportActive")){
				attrPtr->attrValue &= ~PARAMETER_ATTR_NOTIFY;
				attrPtr->attrValue |= PARAMETER_ATTR_ACTIVE_UNSUPPORT;
			}else{
				CMS_LOG(LL_ERROR,"XML error at line %d: NOTIFICATION value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else if(!stricmp(attr, "HEX")){
			if(!stricmp(value, "y"))
			{
				attrPtr->attrValue |= PARAMETER_ATTR_HEX_VALUE;
			}
		}
#if 0
		else if(!stricmp(attr, "HIDEFROMACS"))
		{
			/* object and parameter share the same attribute HIDEFROMACS */
			if(attrPtr->paraFlag != 1){
				checkIfNode = 1;
			}

			if(!stricmp(value, "true"))
			{
				attrPtr->attrValue |= ATTR_HIDEFROMACS;
			}
			else
			{
				attrPtr->attrValue &= ~ATTR_HIDEFROMACS;
			}
		}
#endif
		else if(!stricmp(attr, "WRITABLE"))
		{
			checkIfNode = 1;
			if(!stricmp(value, "true"))
			{
				attrPtr->attrValue |= ATTR_WRITABLE;
			}
			else
			{
				attrPtr->attrValue &= ~ATTR_WRITABLE;
			}
			
		}
		else if(!strcmp(attr, "STORABLE")){
			checkIfNode = 1;
			if(!stricmp(value, "nonconfigured")){
				attrPtr->attrValue |= ATTR_NO_STORABLE;
			}else{
				attrPtr->attrValue &= ~ATTR_NO_STORABLE;
			}
		}
		else if(!stricmp(attr, "EXTATTR"))
		{
			uint16_t tempValue;
#ifdef SYSDEF_PARSER_ON_HOST		
			if(strlen(value)!=6)
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: EXTATTR value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
#endif			
			tempValue = strtoul(value,NULL,16);
#ifdef SYSDEF_PARSER_ON_HOST
			if(tempValue == 0)
			{
				if(strcmp(value,"0x0000") != 0)
				{
					CMS_LOG(LL_ERROR,"XML error at line %d: EXTATTR value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
					errorflag = CMS_NOK;
					return CMS_NOK;
				}
			}
#endif				
			attrtmp = tempValue << 16;
			attrPtr->attrValue |= attrtmp;
//			CMS_LOG(LL_DEBUG,"value=%04x\n\r",attrPtr->attrValue);
			//CMS_LOG(LL_DEBUG,"value=%d\n\r",tempValue);
		}

#ifdef SYSDEF_PARSER_ON_HOST
		else if ( !stricmp( attr, "NOMALLOC" ) )
		{
			if ( !stricmp( value, "y" ) )
			{
				attrPtr->configFlag = 0;
				attrPtr->type = PARAMETER_TYPE_STRING;
				attrPtr->length = sizeof( char * ); // for store an pointer.
				attrPtr->attrValue |= PARAMETER_ATTR_NO_MALLOC;
			}
			else
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: NOMALLOC value \"%s\" error.\n\r", XML_GetCurrentLineNumber( parser ), value );
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else if(!stricmp(attr, "READONLY"))
		{
			if(!stricmp(value, "y"))
				attrPtr->attrValue |= PARAMETER_ATTR_READONLY;
			else if(stricmp(value, "n"))
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: READONLY value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else if(!stricmp(attr, "MAXNODENUMBER"))
		{
			attrPtr->nodeNumber = atoi(value);
			if((attrPtr->nodeNumber < 1) || (attrPtr->nodeNumber > 255)){
				CMS_LOG(LL_ERROR,"XML error at line %d: max node num(%d) should be in range(1~255)",XML_GetCurrentLineNumber(parser),attrPtr->nodeNumber);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else if(!stricmp(attr, "INDEXNODE"))
		{
			checkIfNode = 1;
			if(!stricmp(value, "y"))
				attrPtr->attrValue |= ATTR_INDEXNODE;//Add leafnode parameter
			else if(stricmp(value, "n"))
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: INDEXNODE value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else if(!stricmp(attr, "ALWAYSACTIVE"))
		{
			checkIfNode = 1;
			if(!stricmp(value, "y"))
				attrPtr->attrValue |= ATTR_ALWAYSACTIVE;//Add leafnode parameter
			else if(stricmp(value, "n"))
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: ACTIVENODE value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}		
		else if(!stricmp(attr, "TYPE"))
		{
			for(typePtr=(typeTable_t *)typeTable; typePtr->recType != 0; typePtr++)
			{
				if(!stricmp(value, typePtr->name))
				{
					attrPtr->type = typePtr->recType;
					break;
				}
			}
			if(typePtr->recType == 0)
			{
				CMS_LOG(LL_DEBUG,"XML error at line %d: TYPE value \"%s\" not exist.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else if(!stricmp(attr, "MAX"))
		{
			attrPtr->maxValue = strtoull(value,NULL,0);
			length = strlen(value);
			if(length>20)//20 is biggest length
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
			if(attrPtr->type == 0)
			{
				CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute must write after \"TYPE\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
			if(attrPtr->type == PARAMETER_TYPE_STRING)
			{
				CMS_LOG(LL_ERROR, "XML error at line %d: TYPE=\"string\" conflict between \"MAX\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
			if(attrPtr->type == PARAMETER_TYPE_UINT8 
			|| attrPtr->type == PARAMETER_TYPE_UINT16 
			|| attrPtr->type == PARAMETER_TYPE_UINT32 
			|| attrPtr->type == PARAMETER_TYPE_UINT64
			)
			{
				if(strchr(value,'-'))
				{
					CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
					errorflag = CMS_NOK;
					return CMS_NOK;
				}
				if(attrPtr->type == PARAMETER_TYPE_UINT64 && length==20)//20 is biggest length
				{
					char maxValue[]="18446744073709551615";
					if(maxAndMinValueCheck(maxValue,value))
					{
						CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
						errorflag = CMS_NOK;
						return CMS_NOK;
					}
				}
				if((attrPtr->type == PARAMETER_TYPE_UINT8 && (uint64_t)attrPtr->maxValue>0xff)
				|| (attrPtr->type == PARAMETER_TYPE_UINT16 && (uint64_t)attrPtr->maxValue>0xffff) 
				|| (attrPtr->type == PARAMETER_TYPE_UINT32 && (uint64_t)attrPtr->maxValue>0xffffffff)
				)
				{
					CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
					errorflag = CMS_NOK;
					return CMS_NOK;
				}
			}
			else
			{
				if(strchr(value,'-'))
				{
					if(attrPtr->type == PARAMETER_TYPE_SINT63  && length==20)//20 is biggest length
					{
						char maxValue[]="-9223372036854775808";
						if(maxAndMinValueCheck(maxValue,value))
						{
							CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
							errorflag = CMS_NOK;
							return CMS_NOK;
						}
					}
					if(attrPtr->type == PARAMETER_TYPE_SINT31)
					{
						if(length>11)//11 is biggest length
						{
							CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
							errorflag = CMS_NOK;
							return CMS_NOK;
						}else if(length == 11){//11 is biggest length
							char maxValue[]="-2147483648";
							if(maxAndMinValueCheck(maxValue,value))
							{
								CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
								errorflag = CMS_NOK;
								return CMS_NOK;
							}
						}
					}
					if((attrPtr->type == PARAMETER_TYPE_SINT7 && (int64_t)attrPtr->maxValue<-128) 
					|| (attrPtr->type == PARAMETER_TYPE_SINT15 && (int64_t)attrPtr->maxValue<-32768) 
					)
					{
						CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
						errorflag = CMS_NOK;
						return CMS_NOK;
					}
				}
				else
				{
					if(attrPtr->type == PARAMETER_TYPE_SINT63)
					{
						if(length>19)//19 is biggest length
						{
							CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
							errorflag = CMS_NOK;
							return CMS_NOK;
						}else if(length == 19){//19 is biggest length
							char maxValue[]="9223372036854775807";
							if(maxAndMinValueCheck(maxValue,value))
							{
								CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
								errorflag = CMS_NOK;
								return CMS_NOK;
							}
						}
					}
					if((attrPtr->type == PARAMETER_TYPE_SINT7 && (uint64_t)attrPtr->maxValue>127)
					|| (attrPtr->type == PARAMETER_TYPE_SINT15 && (uint64_t)attrPtr->maxValue>32767)
					|| (attrPtr->type == PARAMETER_TYPE_SINT31 && (uint64_t)attrPtr->maxValue>2147483647)
					)
					{
						CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
						errorflag = CMS_NOK;
						return CMS_NOK;
					}
				}
			}
			maxFlag = 1;
		}
		else if(!stricmp(attr, "MIN"))
		{
			attrPtr->minValue = strtoull(value,NULL,0);
			length = strlen(value);
			if(length>20)//20 is biggest length
			{
				CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
			if(attrPtr->type == 0)
			{
				CMS_LOG(LL_ERROR, "XML error at line %d: \" MIN\" attribute must write after \"TYPE\" attribute\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
			if(attrPtr->type == PARAMETER_TYPE_STRING)
			{
				CMS_LOG(LL_DEBUG, "XML error at line %d: TYPE=\"string\" conflict between \"MIN\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
			if(attrPtr->type == PARAMETER_TYPE_UINT8 
				|| attrPtr->type == PARAMETER_TYPE_UINT16 
				|| attrPtr->type == PARAMETER_TYPE_UINT32 
				|| attrPtr->type == PARAMETER_TYPE_UINT64
				)
			{
				if(strchr(value,'-'))
				{
					CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
					errorflag = CMS_NOK;
					return CMS_NOK;
				}
				if(attrPtr->type == PARAMETER_TYPE_UINT64  && length==20)
				{
					char minValue[]="18446744073709551615";
					if(maxAndMinValueCheck(minValue,value))
					{
						CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
						errorflag = CMS_NOK;
						return CMS_NOK;
					}
				}
				if((attrPtr->type == PARAMETER_TYPE_UINT8 && (uint64_t)attrPtr->minValue>0xff)
				|| (attrPtr->type == PARAMETER_TYPE_UINT16 && (uint64_t)attrPtr->minValue>0xffff) 
				|| (attrPtr->type == PARAMETER_TYPE_UINT32 && (uint64_t)attrPtr->minValue>0xffffffff)
				)
				{
					CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
					errorflag = CMS_NOK;
					return CMS_NOK;
				}
			}
			else
			{
				if(strchr(value,'-'))
				{
					if(attrPtr->type == PARAMETER_TYPE_SINT63  && length==20)
					{
						char minValue[]="-9223372036854775808";
						if(maxAndMinValueCheck(minValue,value))
						{
							CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
							errorflag = CMS_NOK;
							return CMS_NOK;
						}
					}
					if(attrPtr->type == PARAMETER_TYPE_SINT31)
					{
						if(length>11)//11 is biggest length
						{
							CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
							errorflag = CMS_NOK;
							return CMS_NOK;
						}else if(length == 11){//11 is biggest length
							char minValue[]="-2147483648";
							if(maxAndMinValueCheck(minValue,value))
							{
								CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
								errorflag = CMS_NOK;
								return CMS_NOK;
							}
						}
					}
					if((attrPtr->type == PARAMETER_TYPE_SINT7 && (int64_t)attrPtr->minValue<-128) 
					|| (attrPtr->type == PARAMETER_TYPE_SINT15 && (int64_t)attrPtr->minValue<-32768) 
					)
					{
						CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
						errorflag = CMS_NOK;
						return CMS_NOK;
					}	
				}
				else
				{
					if(attrPtr->type == PARAMETER_TYPE_SINT63)
					{
						if(length>19)//19 is biggest length
						{
							CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
							errorflag = CMS_NOK;
							return CMS_NOK;
						}else if(length == 19){//19 is biggest length
							char minValue[]="9223372036854775807";
							if(maxAndMinValueCheck(minValue,value))
							{
								CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
								errorflag = CMS_NOK;
								return CMS_NOK;
							}
						}
					}
					if((attrPtr->type == PARAMETER_TYPE_SINT7 && (uint64_t)attrPtr->minValue>127)
					|| (attrPtr->type == PARAMETER_TYPE_SINT15 && (uint64_t)attrPtr->minValue>32767)
					|| (attrPtr->type == PARAMETER_TYPE_SINT31 && (uint64_t)attrPtr->minValue>2147483647)
					)
					{
						CMS_LOG(LL_ERROR, "XML error at line %d: \"MIN\" attribute value out of range.\n\r",XML_GetCurrentLineNumber(parser));
						errorflag = CMS_NOK;
						return CMS_NOK;
					}
				}
			}
			minFlag = 1;
		}
		else if(!stricmp(attr, "LENGTH"))
		{
#if 1
			if ( attrPtr->attrValue & PARAMETER_ATTR_NO_MALLOC )
			{
				attrPtr->length = sizeof( char * ); // for store an pointer.
			}
			else
#endif
			attrPtr->length = atoi( value ) + 1; // +1 for "\0"
		}
		else if(!strcmp(attr, "PRIORITY"))
		{
			if(!strcmp(value, "HIGHEST")) {
				attrPtr->priValue = 2;
			}else if (!strcmp(value, "MEDIAN")) {
				attrPtr->priValue = 50;
			}else if (!strcmp(value, "LOWEST")) {
				attrPtr->priValue = 99;
			}else {
				attrPtr->priValue = atoi(value);
			}
		}else if(!strcmp(attr, "UPDATE")){
			if(!stricmp(value, "y")){
				attrPtr->updateObjFlag = 1;
			}else{
				attrPtr->updateObjFlag = 0;
			}
		}
		else
		{
			CMS_LOG(LL_ERROR, "XML warning at line %d: Attribute name \"%s\" not exist.\n\r",XML_GetCurrentLineNumber(parser),attr);
		}
#endif		
	}
	if(notifyOff==1 && checkIfNode!=1)
	{
		attrPtr->attrValue &=~PARAMETER_ATTR_NOTIFY;
	}
#ifdef SYSDEF_PARSER_ON_HOST
	if((attrPtr->attrValue & PARAMETER_ATTR_CONFIG) && (attrPtr->attrValue & PARAMETER_ATTR_READONLY))
	{
		CMS_LOG(LL_ERROR, "XML error at line %d: PARAMETER=\"configured\" conflict with READONLY=\"y\" \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
		errorflag = CMS_NOK;
		return CMS_NOK;
	}
	if(attrPtr->type != PARAMETER_TYPE_STRING && attrPtr->length!= 0)
	{
		CMS_LOG(LL_ERROR, "XML error at line %d: Attribute \"LENGTH\" belongs to string.\n\r",XML_GetCurrentLineNumber(parser));
		errorflag = CMS_NOK;
		return CMS_NOK;
	}
	if(attrPtr->type == PARAMETER_TYPE_BOOLEAN)
	{
		attrPtr->minValue = 0;
		attrPtr->maxValue = 1;
	}
	if(attrPtr->type == PARAMETER_TYPE_DATETIME)
		attrPtr->length = PARAMETER_TYPE_DATETIME;
	if(attrPtr->type != PARAMETER_TYPE_STRING && attrPtr->type != 0 && attrPtr->type != PARAMETER_TYPE_MAC
		&& attrPtr->type != PARAMETER_TYPE_DATETIME)
	{
		if(minFlag == 0)
		{
			if(attrPtr->type == PARAMETER_TYPE_UINT8)
				attrPtr->minValue = 0;
			else if(attrPtr->type == PARAMETER_TYPE_UINT16)
				attrPtr->minValue = 0;
			else if(attrPtr->type == PARAMETER_TYPE_UINT32)
				attrPtr->minValue = 0;
			else if(attrPtr->type == PARAMETER_TYPE_UINT64)
				attrPtr->minValue = 0;
			else if(attrPtr->type == PARAMETER_TYPE_SINT7)
				attrPtr->minValue = strtoull("-128",NULL,0);
			else if(attrPtr->type == PARAMETER_TYPE_SINT15)
				attrPtr->minValue = strtoull("-32768",NULL,0);
			else if(attrPtr->type == PARAMETER_TYPE_SINT31)
				attrPtr->minValue = strtoull("-2147483648",NULL,0);
			else if(attrPtr->type == PARAMETER_TYPE_SINT63)
				attrPtr->minValue = strtoull("-9223372036854775808",NULL,0);
		}
		if(maxFlag == 0)
		{
			if(attrPtr->type == PARAMETER_TYPE_UINT8)
				attrPtr->maxValue = 255;
			else if(attrPtr->type == PARAMETER_TYPE_UINT16)
				attrPtr->maxValue = 65535;
			else if(attrPtr->type == PARAMETER_TYPE_UINT32)
				attrPtr->maxValue = strtoull("4294967295",NULL,0);
			else if(attrPtr->type == PARAMETER_TYPE_UINT64)
				attrPtr->maxValue = strtoull("18446744073709551615",NULL,0);
			else if(attrPtr->type == PARAMETER_TYPE_SINT7)
				attrPtr->maxValue = 127;
			else if(attrPtr->type == PARAMETER_TYPE_SINT15)
				attrPtr->maxValue = 32767;
			else if(attrPtr->type == PARAMETER_TYPE_SINT31)
				attrPtr->maxValue = 2147483647;
			else if(attrPtr->type == PARAMETER_TYPE_SINT63)
				attrPtr->maxValue = strtoull("9223372036854775807",NULL,0);
		}
	}	
	if(attrPtr->paraFlag != 1 && (attrPtr->configFlag!=0 || attrPtr->maxValue!=0 || attrPtr->minValue!=0
		|| attrPtr->length!=0 || attrPtr->type!=0 || 
		(attrPtr->attrValue!=0 && !(attrPtr->attrValue & ATTR_INDEXNODE) && !(attrPtr->attrValue & ATTR_ALWAYSACTIVE) && 
		!(attrPtr->attrValue & ATTR_HIDEFROMACS) && !(attrPtr->attrValue & ATTR_WRITABLE) && !(attrPtr->attrValue & ATTR_NO_STORABLE))))
	{//Check parameter attribute exist
		CMS_LOG(LL_ERROR, "XML error at line %d: Parameter must have \"PARAMETER\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
		errorflag = CMS_NOK;
		return CMS_NOK;
	}
	if(attrPtr->paraFlag == 1 && attrPtr->type == 0)
	{
		CMS_LOG(LL_ERROR, "XML error at line %d: PARAMETER must have \"TYPE\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
		errorflag = CMS_NOK;
		return CMS_NOK;
	}
	if(attrPtr->type != PARAMETER_TYPE_STRING && attrPtr->type != 0 && attrPtr->type != PARAMETER_TYPE_MAC
		&& attrPtr->type != PARAMETER_TYPE_DATETIME)
	{
		if((attrPtr->type == PARAMETER_TYPE_UINT8 && ((uint8_t)attrPtr->maxValue<(uint8_t)attrPtr->minValue || (uint8_t)attrPtr->maxValue==(uint8_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_UINT16 && ((uint16_t)attrPtr->maxValue<(uint16_t)attrPtr->minValue || (uint16_t)attrPtr->maxValue==(uint16_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_UINT32 && ((uint32_t)attrPtr->maxValue<(uint32_t)attrPtr->minValue || (uint32_t)attrPtr->maxValue==(uint32_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_UINT64 && ((uint64_t)attrPtr->maxValue<(uint64_t)attrPtr->minValue || (uint64_t)attrPtr->maxValue==(uint64_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_SINT7 && ((int8_t)attrPtr->maxValue<(int8_t)attrPtr->minValue || (int8_t)attrPtr->maxValue==(int8_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_SINT15 && ((int16_t)attrPtr->maxValue<(int16_t)attrPtr->minValue || (int16_t)attrPtr->maxValue==(int16_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_SINT31 && ((int32_t)attrPtr->maxValue<(int32_t)attrPtr->minValue || (int32_t)attrPtr->maxValue==(int32_t)attrPtr->minValue))
			|| (attrPtr->type == PARAMETER_TYPE_SINT63 && ((int64_t)attrPtr->maxValue<(int64_t)attrPtr->minValue || (int64_t)attrPtr->maxValue==(int64_t)attrPtr->minValue))
		)
		{
			CMS_LOG(LL_ERROR, "XML error at line %d: \"MAX\" and \"MIN\" attribute value error.\n\r",XML_GetCurrentLineNumber(parser));
			errorflag = CMS_NOK;
			return CMS_NOK;
		}
	}
	if(attrPtr->type == PARAMETER_TYPE_STRING && attrPtr->length == 0)
	{
		CMS_LOG(LL_ERROR, "XML error at line %d: TYPE=\"string\" must have \"LENGTH\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
		errorflag = CMS_NOK;
		return CMS_NOK;
	}
#endif	
	return 0;
}

int cms_GetAttrValue2(const char **attrs, attrList_t *attrPtr)
{
	char	*attr;
	char *value=NULL;
	int attrIndex = 0;

	while(attrs){
		attr=(char*) attrs[attrIndex++];
		value=(char*) attrs[attrIndex++];
		if(!attr || !value)
			break;

		if(!stricmp(attr, "PARAMETER"))
		{
			attrPtr->paraFlag = 1;
#ifdef SYSDEF_PARSER_ON_HOST			
			if(!stricmp(value, "configured")){
				attrPtr->configFlag = 1;
				attrPtr->attrValue |= PARAMETER_ATTR_CONFIG;
			}
			else if(!stricmp(value, "nonconfigured"))
				attrPtr->configFlag = 0;
			else
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: PARAMETER value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
#else
			if(stricmp(value, "configured"))
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: PARAMETER value should be \"configured\".\n\r",XML_GetCurrentLineNumber(parser));
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
#endif
		}
		else if(!stricmp(attr, "NOTIFICATION"))
		{
			if(!stricmp(value, "active"))
			{
				attrPtr->attrValue |= PARAMETER_ATTR_ACTIVENOTIFY;
				attrPtr->attrValue &=~PARAMETER_ATTR_PASSIVENOTIFY;
			}
			else if(!stricmp(value, "passive"))
			{
				attrPtr->attrValue &=~PARAMETER_ATTR_ACTIVENOTIFY;
				attrPtr->attrValue |= PARAMETER_ATTR_PASSIVENOTIFY;
			}
			else if(!stricmp(value, "off"))
			{
				attrPtr->attrValue &=~PARAMETER_ATTR_NOTIFY;
			}
			else if(stricmp(value, "off"))
			{
				CMS_LOG(LL_ERROR,"XML error at line %d: NOTIFICATION value \"%s\" error.\n\r",XML_GetCurrentLineNumber(parser),value);
				errorflag = CMS_NOK;
				return CMS_NOK;
			}
		}
		else
		{
			CMS_LOG(LL_ERROR, "XML warning at line %d: Attribute name \"%s\" not exist.\n\r",XML_GetCurrentLineNumber(parser),attr);
		}	
	}
	
	return 0;
}


#ifndef	SYSDEF_PARSER_ON_HOST
/* add space in config.rom for each line. */
int printFileSpace( FILE *fp, int depth )
{
	int i = 0, offset = 0;

	for ( i = 0; i < depth; i++ )
		offset += fprintf( fp, "  " );

	return offset;
}

static char *transcode(const char *src, char *dest, int dest_size)
{
	if (src == NULL || dest == NULL)
		goto out;

	while (*src != '\0') {
		switch (*src) {
		case '&':
			strcat(dest, AMP);
			break;
		case '<':
			strcat(dest, LT);
			break;
		case '>':
			strcat(dest, GT);
			break;
		case '\'':
			strcat(dest, APOS);
			break;
		case '"':
			strcat(dest, QUOT);
			break;
		default:
			strncat(dest, src, 1);
			break;
		}

		src++;
	}

	dest[dest_size - 1] = '\0';

out:
	return dest;
}

/*
	Description: 
		function used to write parameter to config.xml.
	Parameters:
		file:
		node:
	return:
		offset
	
*/
int cmsXml_ParseParameter(FILE *file, objectNode_t *node)
{
	parameterValue_t *ptr, *tmp,*typeValue;
	int num = 0, offset = 0;
	uint32_t flags;
	uint16_t attrExtFlag;
	uintptr_t *parameter;
	char **tempParameter;
	//typeTable_t *typePtr;
	uint8_t macStr[6];
	uint16_t count = 0;
	void *tmpPtr = NULL;
	char *nodeName_path;
	//void *obj;
	char addrType[60]={0};
	char *ipAddrType=addrType;
	uint32_t objOffset = 0;
	parameterValue_t *defPtr,*defTmp;
	char **defTempParameter;
	uint32_t defFlags;
	uint16_t defAttrExtFlag;
	char *tmp_buf;
	int tmp_len;;

	num = node->meta_count;
	parameter = malloc(num*sizeof(void *));
	tempParameter = (char **)parameter;
	defTempParameter =  (char **)parameter;

	//tempParameter = parameter;
	while(num > 0){
		*parameter = (uintptr_t)cmsXml_getParameterNamePtr(pdmCB, node, num);
		if ((void *)(*parameter) == NULL){
			num--;
			continue;
		}
		parameter++;
		count++;
		num--;
	}

	num = count;
	/* if IA is not 0, we should do cmsXml_GetObjectByOID to have correct object offset. */
	tmpPtr = cmsXml_GetObjectByOID( pdmCB, pdmTmpOID, pdmTmpIA, ADD_IF_NOT_EXISTED );
	if ( pdmTmpIA )
	{
		objOffset = cmsXmlGetPtrOffset( pdmCB, tmpPtr );
	}
	else
	{
		objOffset = node->object;
	}
	
	tmp = ptr = cmsXml_getParameter(pdmCB, objOffset, num, tempParameter);	
	defTmp = defPtr = cmsXml_getDefaultParameter(pdmCB, objOffset, num, defTempParameter);

	free(tempParameter);
//	num = node->meta_count;
	while(num > 0){
		/* if IA is not 0, we should do cmsXml_GetObjectByOID to have correct object offset. */
		if ( pdmTmpIA )
			flags = cmsXml_getParameterAttr( pdmCB, objOffset, ptr->name );
		else
			flags = cmsXml_getParameterAttr(pdmCB, node->object, ptr->name);
		
		if(flags & PARAMETER_ATTR_CONFIG){
//check NOTIFICATION & EXTATTR
			if ( pdmTmpIA )
				defFlags = cmsXml_getDefaultParameterAttr( pdmCB, objOffset, ptr->name );
			else
				defFlags = cmsXml_getDefaultParameterAttr(pdmCB, node->object, ptr->name);


			/* if IA is not 0, we should do cmsXml_GetObjectByOID to have correct object offset. */
			if ( pdmTmpIA )
				attrExtFlag = cmsXml_getParameterExtAttr( pdmCB, objOffset, ptr->name );
			else
				attrExtFlag = cmsXml_getParameterExtAttr(pdmCB, node->object, ptr->name);

			if ( pdmTmpIA )
				defAttrExtFlag = cmsXml_getDefaultParameterExtAttr( pdmCB, objOffset, ptr->name );
			else
				defAttrExtFlag = cmsXml_getDefaultParameterExtAttr(pdmCB, node->object, ptr->name);

			if(((flags & PARAMETER_ATTR_NOTIFY) && !(defFlags & PARAMETER_ATTR_NOTIFY))
				||((flags & PARAMETER_ATTR_ACTIVENOTIFY) && !(defFlags & PARAMETER_ATTR_ACTIVENOTIFY))
				||((flags & PARAMETER_ATTR_PASSIVENOTIFY) && !(defFlags & PARAMETER_ATTR_PASSIVENOTIFY))
				|| (attrExtFlag!=defAttrExtFlag)){
				//NOTIFICATION or EXTATTR flag is changed
				goto skipValueCheck;
			}else{
				//NOTIFICATION or EXTATTR flag is same as default
			}
//check value
			if(((ptr->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING)||ptr->type_size == PARAMETER_TYPE_DATETIME){
				if(!defPtr->value && (!ptr->value || strlen((char *)ptr->value)==0)){
					goto skipWrite;
				}
				if(!defPtr->value && ptr->value && strlen((char *)ptr->value)==1 && stricmp((char *)ptr->value,"0")==0){
					goto skipWrite;
				}
				if(defPtr->value && ptr->value && strcmp((char *)ptr->value,(char *)defPtr->value)==0){
					goto skipWrite;
				}
				
				/*Don't need to save below parameters when addressingtype is DHCP or DHCPv6*/
				if((strcmp(ptr->name,"DNSServers")==0)||(strcmp(ptr->name,"DefaultGateway")==0)||
					(strcmp(ptr->name,"SubnetMask")==0)||(strcmp(ptr->name,"ExternalIPAddress")==0)){
					nodeName_path = cmsXml_getFullPathByID(pdmCB, node->object);
					if(strstr(nodeName_path,"WANIPConnection")!=NULL){
						strcpy(addrType,"AddressingType");
						if(tmpPtr!=NULL){
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"DHCP")==0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								cmsXml_freeFullPathBuffer((void **)&nodeName_path);
								goto skipWrite;
							}
							cmsXml_freeParameterBuffer(typeValue, 1);
						}
					}
					else if(strstr(nodeName_path,"WANPPPConnection")!=NULL){
						if(tmpPtr!=NULL){
							cmsXml_freeFullPathBuffer((void **)&nodeName_path);
							goto skipWrite;
						}
					}
					cmsXml_freeFullPathBuffer((void **)&nodeName_path);
				}
				else if(strcmp(ptr->name,"X_CT-COM_IPv6DNSServers") == 0){
					
					memset(addrType, 0, sizeof(addrType));
					strcpy(addrType,"X_GC_COM_IPv6IPGetMethodOrigin");
					if(tmpPtr!=NULL){
						typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
						if(strcmp(typeValue->value,"Auto") == 0){
							cmsXml_freeParameterBuffer(typeValue, 1);
							goto skipWrite;
						}else if(!strcmp(typeValue->value,"Manual")){
							memset(addrType, 0, sizeof(addrType));
							strcpy(addrType,"X_GC_COM_IPv6DNSFromOrigin");
							cmsXml_freeParameterBuffer(typeValue, 1);
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"Static") != 0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								goto skipWrite;
							}
						}
						cmsXml_freeParameterBuffer(typeValue, 1);
					}
					
				}
				else if(strcmp(ptr->name,"X_CT-COM_IPv6IPAddress") == 0){
					memset(addrType, 0, sizeof(addrType));
					strcpy(addrType,"X_GC_COM_IPv6IPGetMethodOrigin");
					if(tmpPtr!=NULL){
						typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
						if(strcmp(typeValue->value,"Auto") == 0){
							cmsXml_freeParameterBuffer(typeValue, 1);
							goto skipWrite;
						}else if(!strcmp(typeValue->value,"Manual")){
							memset(addrType, 0, sizeof(addrType));
							strcpy(addrType,"X_CT-COM_IPv6IPAddressOrigin");
							cmsXml_freeParameterBuffer(typeValue, 1);
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"Static") != 0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								goto skipWrite;
							}
						}
						cmsXml_freeParameterBuffer(typeValue, 1);
					}
					
				}
				else if(strcmp(ptr->name,"X_CT-COM_DefaultIPv6Gateway") == 0){
					nodeName_path = cmsXml_getFullPathByID(pdmCB, node->object);
					if(strstr(nodeName_path,"WANIPConnection")!=NULL){
						memset(addrType, 0, sizeof(addrType));
						strcpy(addrType,"X_GC_COM_IPv6IPGetMethodOrigin");
						if(tmpPtr!=NULL){
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"Auto") == 0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								cmsXml_freeFullPathBuffer((void **)&nodeName_path);
								goto skipWrite;
							}else if(!strcmp(typeValue->value,"Manual")){
								memset(addrType, 0, sizeof(addrType));
								strcpy(addrType,"X_GC_COM_IPv6GWFromOrigin");
								cmsXml_freeParameterBuffer(typeValue, 1);
								typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
								if(strcmp(typeValue->value,"Static") != 0){
									cmsXml_freeParameterBuffer(typeValue, 1);
									cmsXml_freeFullPathBuffer((void **)&nodeName_path);
									goto skipWrite;
								}
							}
							cmsXml_freeParameterBuffer(typeValue, 1);
						}
					}
					cmsXml_freeFullPathBuffer((void **)&nodeName_path);
				}
				else if(strcmp(ptr->name,"X_CT-COM_IPv6Prefix") == 0){
					
					memset(addrType, 0, sizeof(addrType));
					strcpy(addrType,"X_GC_COM_IPv6IPGetMethodOrigin");
					if(tmpPtr!=NULL){
						typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
						if(strcmp(typeValue->value,"Auto") == 0){
							memset(addrType, 0, sizeof(addrType));
							strcpy(addrType,"X_CT-COM_IPv6PrefixOrigin");
							cmsXml_freeParameterBuffer(typeValue, 1);
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"Static") != 0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								goto skipWrite;
							}
						}else if(!strcmp(typeValue->value,"Manual")){
							memset(addrType, 0, sizeof(addrType));
							strcpy(addrType,"X_CT-COM_IPv6PrefixOrigin");
							cmsXml_freeParameterBuffer(typeValue, 1);
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"Static") != 0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								goto skipWrite;
							}
						}
						cmsXml_freeParameterBuffer(typeValue, 1);
					}
					
				}
				else if(strcmp(ptr->name,"Prefix")==0){
					nodeName_path = cmsXml_getFullPathByID(pdmCB, node->object);
					if(strstr(nodeName_path,"PrefixInformation")!=NULL){
						strcpy(addrType,"Mode");
						if(tmpPtr != NULL){
							typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
							if(strcmp(typeValue->value,"WANDelegated")==0){
								cmsXml_freeParameterBuffer(typeValue, 1);
								cmsXml_freeFullPathBuffer((void **)&nodeName_path);
								goto skipWrite;
							}
							cmsXml_freeParameterBuffer(typeValue, 1);	
						}
					}
					cmsXml_freeFullPathBuffer((void **)&nodeName_path);	
				}
				else if(strcmp(ptr->name,"X_CT-COM_Aftr")==0){
					/*not save ipv6 aftr address to romefile*/
					strcpy(addrType,"X_CT-COM_AftrMode");
					if(tmpPtr!=NULL){
						typeValue=cmsXml_getParameter(pdmCB, objOffset, 1, (char **)(&ipAddrType));
						/*Aftr_Mode 0, not save to romefile */
						if((*(uint8_t *)typeValue->value)==0){
							cmsXml_freeParameterBuffer(typeValue, 1);
							goto skipWrite;
						}
						cmsXml_freeParameterBuffer(typeValue, 1);	
					}
				}
			}else if(ptr->type_size == PARAMETER_TYPE_MAC){
				if(!defPtr->value && (!ptr->value || strlen((char *)ptr->value)==0)){
					goto skipWrite;
				}
				if(defPtr->value && ptr->value && memcmp(ptr->value,defPtr->value,6)==0){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_BOOLEAN||ptr->type_size == PARAMETER_TYPE_UINT8){
				if(((uint8_t *)defPtr->value)==NULL && *((uint8_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((uint8_t *)defPtr->value)!=NULL && *((uint8_t *)defPtr->value) == *((uint8_t *)ptr->value)){
					goto skipWrite;
				}
			}
			else if(ptr->type_size == PARAMETER_TYPE_UINT16){
				if(((uint16_t *)defPtr->value)==NULL && *((uint16_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((uint16_t *)defPtr->value)!=NULL && *((uint16_t *)defPtr->value) == *((uint16_t *)ptr->value)){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_UINT32){
				if(((uint32_t *)defPtr->value)==NULL && *((uint32_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((uint32_t *)defPtr->value)!=NULL && *((uint32_t *)defPtr->value) == *((uint32_t *)ptr->value)){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_UINT64){
				if(((uint64_t *)defPtr->value)==NULL && *((uint64_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((uint64_t *)defPtr->value)!=NULL && *((uint64_t *)defPtr->value) == *((uint64_t *)ptr->value)){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_SINT7){
				if(((int8_t *)defPtr->value)==0 && *((int8_t *)ptr->value)==0){//check it default 0
					goto skipWrite;
				}
				if(((int8_t *)defPtr->value)!=0 && *((int8_t *)defPtr->value) == *((int8_t *)ptr->value)){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_SINT15){
				if(((int16_t *)defPtr->value)==0 && *((int16_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((int16_t *)defPtr->value)!=0 && *((int16_t *)defPtr->value) == *((int16_t *)ptr->value)){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_SINT31){	
				if(((int32_t *)defPtr->value)==0 && *((int32_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((int32_t *)defPtr->value)!=0 && *((int32_t *)defPtr->value) == *((int32_t *)ptr->value)){
					goto skipWrite;
				}
			}else if(ptr->type_size == PARAMETER_TYPE_SINT63){
				if(((int64_t *)defPtr->value)==0 && *((int64_t *)ptr->value)==0){
					goto skipWrite;
				}
				if(((int64_t *)defPtr->value)!=0 && *((int64_t *)defPtr->value) == *((int64_t *)ptr->value)){
					goto skipWrite;
				}
			}
skipValueCheck:
			offset += printFileSpace( file, fileSpaceDepth );
			offset += fprintf(file,"<%s", ptr->name);
			offset += fprintf(file," PARAMETER=\"configured\"");
#if 0
			if(flags & PARAMETER_ATTR_READONLY)
				offset += fprintf(file," READONLY=%s", "\"y\"");
#endif
			if(flags & PARAMETER_ATTR_ACTIVENOTIFY)
				offset += fprintf(file," NOTIFICATION=\"active\"");
			if(flags & PARAMETER_ATTR_PASSIVENOTIFY)
				offset += fprintf(file," NOTIFICATION=\"passive\"");

			offset += fprintf(file,">");
#if 0
			if(flags & PARAMETER_ATTR_HEX_VALUE)
				offset += fprintf(file," HEX=%s", "\"y\"");
				

			if(attrExtFlag != 0)
				offset += fprintf(file," EXTATTR=\"0x%04x\"",attrExtFlag);

			if((ptr->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING)
			{
				offset += fprintf(file," TYPE=\"string\"");
				offset += fprintf(file," LENGTH=\"%d\">", (int)(ptr->type_size-PARAMETER_TYPE_STRING-1)); //-1 for "\0"
			}else{
				for(typePtr=(typeTable_t *)typeTable; typePtr->recType != 0; typePtr++)
				{
					if(ptr->type_size == typePtr->recType)
					{
						offset += fprintf(file," TYPE=\"%s\"", typePtr->name);
						if(typePtr->recType == PARAMETER_TYPE_UINT8)
						{
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%x\"", ptr->max.unsign.u8);
								offset += fprintf(file," MIN=\"0X%x\">", ptr->min.unsign.u8);
							}else{
								offset += fprintf(file," MAX=\"%u\"", ptr->max.unsign.u8);
								offset += fprintf(file," MIN=\"%u\">", ptr->min.unsign.u8);
							}	
						}
						else if(typePtr->recType == PARAMETER_TYPE_UINT16)
						{
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%x\"", ptr->max.unsign.u16);
								offset += fprintf(file," MIN=\"0X%x\">", ptr->min.unsign.u16);
							}else{
								offset += fprintf(file," MAX=\"%u\"", ptr->max.unsign.u16);
								offset += fprintf(file," MIN=\"%u\">", ptr->min.unsign.u16);
							}
						}
						else if(typePtr->recType == PARAMETER_TYPE_UINT32)
						{
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%x\"", ptr->max.unsign.u32);
								offset += fprintf(file," MIN=\"0X%x\">", ptr->min.unsign.u32);
							}else{
								offset += fprintf(file," MAX=\"%u\"", ptr->max.unsign.u32);
								offset += fprintf(file," MIN=\"%u\">", ptr->min.unsign.u32);
							}
						}
						else if(typePtr->recType == PARAMETER_TYPE_MAC)
						{
							offset += fprintf(file,">");
						}
						else if(typePtr->recType == PARAMETER_TYPE_UINT64)
						{	
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%llx\"", ptr->max.unsign.u64);
								offset += fprintf(file," MIN=\"0X%llx\">", ptr->min.unsign.u64);
							}else{
								offset += fprintf(file," MAX=\"%llu\"", ptr->max.unsign.u64);
								offset += fprintf(file," MIN=\"%llu\">", ptr->min.unsign.u64);
							}
						}
						else if(typePtr->recType == PARAMETER_TYPE_BOOLEAN)
						{
							offset += fprintf(file,">");
						}
						else if(typePtr->recType == PARAMETER_TYPE_DATETIME)
						{
							offset += fprintf(file,">");
						}
						else if(typePtr->recType == PARAMETER_TYPE_SINT7)
						{	
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%x\"", ptr->max.sign.s7);
								offset += fprintf(file," MIN=\"0X%x\">", ptr->min.sign.s7);
							}else{
								offset += fprintf(file," MAX=\"%d\"", ptr->max.sign.s7);
								offset += fprintf(file," MIN=\"%d\">", ptr->min.sign.s7);
							}
						}
						else if(typePtr->recType == PARAMETER_TYPE_SINT15)
						{
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%x\"", ptr->max.sign.s15);
								offset += fprintf(file," MIN=\"0X%x\">", ptr->min.sign.s15);
							}else{
								offset += fprintf(file," MAX=\"%d\"", ptr->max.sign.s15);
								offset += fprintf(file," MIN=\"%d\">", ptr->min.sign.s15);
							}
						}
						else if(typePtr->recType == PARAMETER_TYPE_SINT31)
						{	
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%x\"", ptr->max.sign.s31);
								offset += fprintf(file," MIN=\"0X%x\">", ptr->min.sign.s31);
							}else{
								offset += fprintf(file," MAX=\"%d\"", ptr->max.sign.s31);
								offset += fprintf(file," MIN=\"%d\">", ptr->min.sign.s31);
							}
						}
						else if(typePtr->recType == PARAMETER_TYPE_SINT63)
						{	
							if(flags & PARAMETER_ATTR_HEX_VALUE){
								offset += fprintf(file," MAX=\"0X%llx\"", ptr->max.sign.s63);
								offset += fprintf(file," MIN=\"0X%llx\">", ptr->min.sign.s63);
							}else{
								offset += fprintf(file," MAX=\"%lld\"", ptr->max.sign.s63);
								offset += fprintf(file," MIN=\"%lld\">", ptr->min.sign.s63);
							}
						}
						break;
					}
				}
			}
#endif
			if ((ptr->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING)
			{
				tmp_len = strlen(ptr->value) * MAX_EXPAND_SIZE + 1;
				tmp_buf = calloc(1, tmp_len);
				if (tmp_buf != NULL) {
					transcode(ptr->value, tmp_buf, tmp_len);
					offset += fprintf(file,"%s", tmp_buf);
					free(tmp_buf);
				} else {
					CMS_LOG(LL_ERROR, "calloc failed, do not transcode.");
					offset += fprintf(file,"%s", (char *)ptr->value);
				}
			}
			else if(ptr->type_size == PARAMETER_TYPE_DATETIME)
			{
				offset += fprintf(file,"%s", (char *)ptr->value);
			}
			else if(ptr->type_size == PARAMETER_TYPE_MAC)
			{
				memcpy(macStr,ptr->value,6);
				offset += fprintf(file,"%02x:%02x:%02x:%02x:%02x:%02x",macStr[0],macStr[1],macStr[2],macStr[3],macStr[4],macStr[5]);
			}
			else{
				switch(ptr->type_size){
				case PARAMETER_TYPE_UINT8:
				case PARAMETER_TYPE_BOOLEAN:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%x", *((uint8_t *)ptr->value));		
					}else{
						offset += fprintf(file,"%u", *((uint8_t *)ptr->value));		
					}
					break;
				case PARAMETER_TYPE_UINT16:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%x", *((uint16_t *)ptr->value));
					}else{
						offset += fprintf(file,"%u", *((uint16_t *)ptr->value));
					}
					break;
				case PARAMETER_TYPE_UINT32:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%x", *((uint32_t *)ptr->value));
					}else{
						offset += fprintf(file,"%u", *((uint32_t *)ptr->value));
					}
					break;
				case PARAMETER_TYPE_UINT64:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%jx", *((uint64_t *)ptr->value));
					}else{
						offset += fprintf(file,"%ju", *((uint64_t *)ptr->value));
					}
					break;
				case PARAMETER_TYPE_SINT7:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%x", *((int8_t *)ptr->value));	
					}else{
						offset += fprintf(file,"%d", *((int8_t *)ptr->value));	
					}
					break;
				case PARAMETER_TYPE_SINT15:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%x", *((int16_t *)ptr->value));		
					}else{
						offset += fprintf(file,"%d", *((int16_t *)ptr->value));	
					}
					break;
				case PARAMETER_TYPE_SINT31:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%x", *((int32_t *)ptr->value));		
					}else{
						offset += fprintf(file,"%d", *((int32_t *)ptr->value));
					}					
					break;
				case PARAMETER_TYPE_SINT63:
					if(flags & PARAMETER_ATTR_HEX_VALUE){
						offset += fprintf(file,"0X%jx", *((int64_t *)ptr->value));		
					}else{
						offset += fprintf(file,"%jd", *((int64_t *)ptr->value));
					}	
					break;	
				}
			}
			offset += fprintf(file,"</%s>\n", ptr->name);
		}

skipWrite:
		defPtr++;
		ptr++;
		num--;
	}

	cmsXml_freeParameterBuffer(tmp, node->meta_count);
	cmsXml_freeParameterBuffer(defTmp, node->meta_count);

	return offset;
}

/*
	Description: 
		function used to write "i" node to config.xml.
	Parameters:
		file: File
		node:
		indexNodeFlagPtr:
	return:
		offset
	
*/
int cmsXml_ParseChildi(FILE *file, objectNode_t *node, indexNodeFlagList_t *indexNodeFlagPtr)
{	
	char *nodeName;
	objectNode_t *tmp;
	int offset = 0;
	int depth = 0, index = 0, tmpOID = 0;
	uint64_t tmpIA = 0;
	cmsoffset_t getOffset = 0;
	int indexRecord = 1; /*init index i record value*/

	nodeName = cmsXmlGetObjRealAddr(pdmCB, node->name);
	CMS_LOG(LL_FLOOD, "name:%s\n", nodeName);
	/* get current depth. */
	depth = cmsXmlGetIADepth( cmsXmlGetPreObjIA( pdmCB, node->object ) );

	/* start to find the next node which belonged to this parents IA. */
	getOffset = cmsXmlGetPreObjNext( pdmCB, node->object );
	while ( getOffset )
	{
		if ( ( cmsXmlGetPreObjAttr( pdmCB, getOffset ) & ATTR_NODECONFIGURED ) && compareIAByDepth( pdmTmpIA, cmsXmlGetPreObjIA( pdmCB, getOffset ), depth - 1 ) )
		{CMS_LOG(LL_FLOOD,"enter n OID %d, child configured\n",pdmTmpOID);
			tmpIA = pdmTmpIA;
			tmpOID = pdmTmpOID;

			pdmTmpIA = cmsXmlGetPreObjIA( pdmCB, getOffset );
			index = cmsXmlGetIAInfo( pdmTmpIA, depth );
			if((index <= 0) || (index >255)){
				index = indexRecord;
			}
			offset += printFileSpace( file, fileSpaceDepth );
			fileSpaceDepth++;
			offset += fprintf( file, "<i%d>\n", index );

			if ( node->attributes & ATTR_OBJECTNODE )
			{
				offset += cmsXml_ParseParameter( file, node );
			}
			if ( ( tmp = cmsXmlGetObjRealAddr( pdmCB, node->child ) ) != NULL )
			{
				offset += cmsXml_ParseNodeToBuf( file, tmp, indexNodeFlagPtr );
			}
			pdmTmpIA = tmpIA;
			pdmTmpOID = tmpOID;

			offset += printFileSpace( file, fileSpaceDepth - 1 );
			offset += fprintf( file, "</i%d>\n", index );
			fileSpaceDepth--;
			indexRecord++;
		}

		/* continue get next node. */
		getOffset = cmsXmlGetPreObjNext( pdmCB, getOffset );
	}

	return offset;
}

/*
	Description: 
		function parse Index child node data to buffer.
	Parameters:
		file: File
		node:
		tempPtr:
		indexNodeFlagPtr: 
	return:
		offset
	
*/
int cmsXml_ParseChild(FILE *file, objectNode_t *node, objectNode_t **tempPtr, indexNodeFlagList_t *indexNodeFlagPtr)
{	
	char *nodeName;
	objectNode_t *tmp;
	long pos;//, pos1;
	int offset = 0, flag = 0, fd;

	nodeName = cmsXmlGetObjRealAddr(pdmCB, node->name);
	CMS_LOG(LL_FLOOD, "name:%s\n", nodeName);
	if(*nodeName == 'i'){
		*tempPtr = node;
	}
	else if((node->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED)	/*the node is been configured*/
	{
		indexNodeFlagPtr->flag=CMS_PDM_INDEXCHILD_CONFIGURED;	/*mark one of index child has been configured!!*/
		offset += fprintf(file,"<i%s>\n",nodeName);
		if(node->attributes & ATTR_OBJECTNODE)
			offset += cmsXml_ParseParameter(file, node);
		if((tmp = cmsXmlGetObjRealAddr(pdmCB, node->child)) != NULL)
		{
			offset += cmsXml_ParseNodeToBuf(file, tmp, indexNodeFlagPtr);
		}
		offset += fprintf(file,"</i%s>\n",nodeName);
	}
	else{	/*the node is not configured, check child status*/
		flag = indexNodeFlagPtr->flag;
		indexNodeFlagPtr->flag = 0;
		pos = ftell(file);	/*store file pos*/
		offset += fprintf(file,"<i%s>\n",nodeName);
		if(node->attributes & ATTR_OBJECTNODE)
			offset += cmsXml_ParseParameter(file, node);
		if((tmp = cmsXmlGetObjRealAddr(pdmCB, node->child)) != NULL)
		{
			offset += cmsXml_ParseNodeToBuf(file, tmp, indexNodeFlagPtr);
		}
		offset += fprintf(file,"</i%s>\n",nodeName);

		if (indexNodeFlagPtr->flag != CMS_PDM_CHILDOFINDEX_CONFIGURED){
			/*this index child doesn't contain any child has been configured*/
//			fseek(file, (0 - offset), SEEK_CUR);
			//pos1 = 
			if(ftell(file) == -1){	/*store file pos*/
				CMS_LOG(LL_FLOOD,  "ftell fail, errno %x.\r\n",errno);
			}
			fd = fileno(file);
			if (ftruncate(fd, pos) < 0){
				CMS_LOG(LL_FLOOD,  "ftruncate fail, errno %x.\r\n",errno);
				//CMS_LOG(LL_DEBUG,"ftruncate fail:%d\r\n", errno);
			}
			fseek(file, (0 - offset), SEEK_CUR);
			offset = 0;
			indexNodeFlagPtr->flag = flag;
		}
		else{
			/*this index child is configured!!*/
			indexNodeFlagPtr->flag = CMS_PDM_INDEXCHILD_CONFIGURED;
		}
		
		
	}
	
	return offset;
}

/*
	Description: 
		function parse Index node data to buffer.
	Parameters:
		file: File
		node:
		tempPtr:
		indexNodeFlagPtr: 
	return:
		offset
	
*/
int cmsXml_ParseIndexNode(FILE *file, objectNode_t *node, objectNode_t **tempPtr, indexNodeFlagList_t *indexNodeFlagPtr)
{	
	objectNode_t *tmp;
	int offset = 0, count = 0, i = 1;

	CMS_LOG(LL_FLOOD, "enter\n");
	offset += cmsXml_ParseChild(file, node, tempPtr, indexNodeFlagPtr);

	count = node->sibling.child_count;
	while(count > 0){
		tmp = node + i;
		offset += cmsXml_ParseChild(file, tmp, tempPtr, indexNodeFlagPtr);
		i++;
		count--;
	}

	return offset;
}

/*
	Description: 
		function used to write node name and attribute to config.xml.
	Parameters:
		file: File
		node:
		indexNodeFlagPtr: 
	return:
		0 or offset
	
*/
int cmsXml_ParseNodeToBuf(FILE *file, objectNode_t *node, indexNodeFlagList_t *indexNodeFlagPtr)
{
	indexNodeFlagList_t *tempFlagPtr = NULL;
	objectNode_t *temp = NULL;
	char *nodeName = NULL;
	int offset = 0;
	int parameterOffset = 0;
	int nodeToBufOffset = 0;
	long pos;//,pos1;
	int fd;

	if(!node)
		return 0;

	nodeName = cmsXmlGetObjRealAddr(pdmCB, node->name);

	/* update pdmCB information. */
	pdmTmpOID = cmsXml_GetOIDByOffset( pdmCB, node->object );
	CMS_LOG(LL_FLOOD, "enter name:%s, OID %d\n", nodeName,pdmTmpOID);

	if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		CMS_LOG(LL_FLOOD, "enter name:%s, OID %d, attr is index child\n", nodeName,pdmTmpOID);

		/* check this prototype node has "Next" or not. And check storable attr*/
		if ( cmsXmlGetPreObjNext( pdmCB, node->object ) && (node->attributes & ATTR_NO_STORABLE) != ATTR_NO_STORABLE )
			offset += cmsXml_ParseChildi( file, node, tempFlagPtr );
	}
	else{
		if ((indexNodeFlagPtr != NULL)&&(indexNodeFlagPtr->flag != CMS_PDM_INDEXCHILD_CONFIGURED)&&((node->attributes & ATTR_NODECONFIGURED)==ATTR_NODECONFIGURED)){
			indexNodeFlagPtr->flag = CMS_PDM_CHILDOFINDEX_CONFIGURED;	/*mark one node of the index child has been configured!!*/
			CMS_LOG(LL_FLOOD, "enter name:%s, OID %d, index child configured\n", nodeName,pdmTmpOID);
		}
		if ((node->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED){

			CMS_LOG(LL_FLOOD, "enter name:%s, OID %d, object configured.\n", nodeName,pdmTmpOID);
			nodeName = cmsXmlGetObjRealAddr(pdmCB, node->name);
			pos = ftell(file);
			offset += printFileSpace( file, fileSpaceDepth );
			fileSpaceDepth++;
			offset += fprintf(file,"<%s>\n",nodeName);

			if(node->attributes & ATTR_OBJECTNODE)
			{
				parameterOffset = cmsXml_ParseParameter(file, node);
				if(parameterOffset)
					offset += parameterOffset;
				//offset += cmsXml_ParseParameter(file, node);
			}
			if((temp = cmsXmlGetObjRealAddr(pdmCB, node->child)) != NULL)
			{
				nodeToBufOffset = cmsXml_ParseNodeToBuf(file, temp, indexNodeFlagPtr);
				if(nodeToBufOffset)
					offset += nodeToBufOffset;
				//offset += cmsXml_ParseNodeToBuf(file, temp, indexNodeFlagPtr);
			}
			if(parameterOffset == 0 && nodeToBufOffset == 0)
			{
				if(ftell(file) == -1){	/*store file pos*/
					CMS_LOG(LL_FLOOD,  "ftell fail, errno %x.\r\n",errno);
				}
				fd = fileno(file);
				if (ftruncate(fd, pos) < 0){
					CMS_LOG(LL_FLOOD, "ftruncate fail, errno %x.\r\n", errno);
				}
				fseek(file, (0 - offset), SEEK_CUR);
				offset = 0;
			}
			else
			{
				offset += printFileSpace( file, fileSpaceDepth - 1 );
				offset += fprintf(file,"</%s>\n", nodeName);
		}
			fileSpaceDepth--;
		}
		if(node->sibling.tree.prev){
			offset += cmsXml_ParseNodeToBuf(file, cmsXmlGetObjRealAddr(pdmCB, node->sibling.tree.prev), indexNodeFlagPtr);
		}
		if(node->sibling.tree.next){
			offset += cmsXml_ParseNodeToBuf(file, cmsXmlGetObjRealAddr(pdmCB, node->sibling.tree.next), indexNodeFlagPtr);
		}
		
	}
	return offset;
}

/*
	Description: 
		function used to save ram to rom.
	Parameters:
		xmlShmCb: XmlContrlBlock
		filename:
	return:
		0: CMS_OK
		-1: fail
	
*/
int cmsXml_SaveRamToRom(cmsXmlCb_t *xmlShmCb, const char *filename)
{
	FILE *file = NULL;
	int fileFd = -1;

	file = fopen(CMS_CUR_FILE_XML, "w+");
	if(file == NULL)
	{
		CMS_LOG(LL_ERROR, "fopen %s fail.", CMS_CUR_FILE_XML);
		return CMS_NOK;
	}
	
	pdmCB=xmlShmCb;
	fprintf(file,"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");

	/* initial pdmCB information. */
	pdmTmpOID = 0;
	pdmTmpIA = 0;

	cmsXml_ParseNodeToBuf(file, pdmCB->rootNode, NULL);

	fflush(file);
	fileFd = fileno(file);
	if(fileFd !=  1){
		fsync(fileFd);
	}
	
	fclose(file);

	return 0;
}
#endif

/*
	Description: 
		function used to init user data value.
	Parameters:
		udRaw: user data structure pointer
	return:
	
*/
static void cmsXml_UserDataInit(void *udRaw)
{
	userData_t	*ud=udRaw;

	memset(ud, 0, sizeof(*ud));
	ud->state = StateStart;
	ud->parameterNamePtr = NULL;
	ud->parameterList = NULL;
	ud->parentList = NULL;
	ud->contentFlag= 0;
	ud->text = NULL;
	ud->textlen = 0;
	ud->nodeToParaFlag = 0;
	ud->parameterNum = 0;
	ud->tagStack = NULL;
	ud->configHead = NULL;
	ud->configCurrent = NULL;
	ud->currentIA = 0;
	ud->currentOffset = 0;

	return;
}

#ifdef SYSDEF_PARSER_ON_HOST

/*
	Description: 
		function used to set parameter value to xml shm.
	Parameters:
		ud: user data structure pointer
	return:
		0: Ok
		-1: error
	
*/
int cms_setParameter(userData_t *ud)
{
	char **tempParameterPtr;
	char *parameter;
	parameterList_t *tempPtr;
	int num = 0;
	uint32_t type = 0, *type_p;
	parameterList_t *paraList;
	parentList_t *parentList;
	int ret = 0;
	char *emptyStr = "", *meta;
	uint8_t meta_len = 0;
	cmsoffset_t paraOffset, attrOffset;
	uint32_t size = 0, type_size = 0;
	void *object;
	
	parentList = ud->parentList;
	paraList = ud->parameterList;
	tempPtr = paraList;
	parameter = malloc(ud->parameterNum*sizeof(void*)*3);//three pointer: name, value and type
	tempParameterPtr = (char **)parameter;
	
	cmsXml_NodeAddObject(ud->configCurrent, ud->parameterList);
	num = ud->parameterNum;

	while(num){
		memcpy(parameter, &paraList->name, sizeof(void *));
		parameter=parameter+sizeof(void*);
		/* If user does not input initial value of a parameter,
			we use an empty string to substitute it. */
		if(paraList->attrValue & PARAMETER_ATTR_CONFIG)
		{
			if(paraList->value){
				memcpy(parameter, &paraList->value, sizeof(void *));
			}else{
				memcpy(parameter, &emptyStr, sizeof(void *));//if sysdef.xml parameter has no value, input empty string.
			}
		}else{
			memcpy(parameter, &paraList->value, sizeof(void *));
		}
		parameter=parameter+sizeof(void*);
		type = PARAMETER_TYPE_STRING ;
		type_p = &type;

		memcpy(parameter, &type_p, sizeof(void *));
		parameter=parameter+sizeof(void*);
		paraList = paraList->next;
		num--;
	}

	num = ud->parameterNum;

	ret=cmsXmlSetParameter(pdmCB, ud->configCurrent->object, num, tempParameterPtr);
	if(ret == CMS_NOK)
		goto errorReturn;
	free(tempParameterPtr);
	paraList=tempPtr;
	num = ud->parameterNum;
	while(num){
		cmsXmlSetParameterAttr(pdmCB, ud->configCurrent->object, paraList->name, paraList->attrValue, 1);
 /*add for default value*/	
		if ((paraList->attrValue & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
			/*set parameter default value*/
			if (cmsXml_SearchParameter(pdmCB, ud->configCurrent, paraList->name, &meta) == CMS_OK){
				object = cmsXmlGetObjRealAddr(pdmCB, NTOHDL(ud->configCurrent->object));
				meta_len = *((uint8_t *)meta);
				memcpy(&type_size, (meta+meta_len-sizeof(uint32_t)), sizeof(uint32_t));
				type_size = NTOHL(type_size);
				size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
				paraOffset = NTOHDL(*((cmsoffset_t *)(meta + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
				memcpy((object+paraOffset+size), (object+paraOffset), size);
			}
			else{
				CMS_LOG(LL_ERROR, "cannot find paramter, should be error, name:%s!!\r\n", paraList->name);
			}
		}

 /*add for default attr*/	
		if ((paraList->attrValue & PARAMETER_ATTR_DEFAULTATTR)== PARAMETER_ATTR_DEFAULTATTR){
			/*set parameter default attr*/
			if (cmsXml_SearchParameter(pdmCB, ud->configCurrent, paraList->name, &meta) == CMS_OK){
				object = cmsXmlGetObjRealAddr(pdmCB, NTOHDL(ud->configCurrent->object));
				meta_len = *((uint8_t *)meta);
				attrOffset = NTOHDL(*((cmsoffset_t *)(meta + meta_len - (sizeof(cmsoffset_t)+sizeof(uint32_t)))));
				size = sizeof(uint32_t);
				memcpy((object+attrOffset+size), (object+attrOffset), size);
			}
			else{
				CMS_LOG(LL_ERROR, "cannot find paramter, should be error, name:%s!!\r\n", paraList->name);
			}
		}


		
		paraList = paraList->next;
		num--;
	}
	paraList=tempPtr;
	num = ud->parameterNum;
	while(num){
		if(paraList) {
			tempPtr = paraList->next;
			if(paraList->name) {
				free(paraList->name);
			}
			if(paraList->value) {
				free(paraList->value);
			}
			free(paraList);
			paraList = tempPtr;
			num--;
		} else {
			break;
		}
	}
	ud->parameterNum = 0;
	ud->parameterList = NULL;
	cmsXml_regObjectId(ud->configCurrent, parentList->next);
	return ret;
	
errorReturn:
	return ret;
}

/*
	Description: 
		function used to handle 64 bits endian transform.
	Parameters:
		value:
	return:
		endian;
*/
static uint64_t cms_transForm64Endian(uint64_t value){
#if defined(SYSDEF_PARSER_ON_HOST) && defined(BIGENDIAN)
	uint32_t *endianPtr;
	uint32_t endian1 = 0;
	uint32_t endian2 = 0;
	uint64_t endian = 0;

	endianPtr = (uint32_t *)&value;
	memcpy(&endian1, endianPtr, sizeof(uint32_t));
	memcpy(&endian2, endianPtr + 1, sizeof(uint32_t));
	endian1 = HTONL(endian1);
	endian2 = HTONL(endian2);
	endianPtr = (uint32_t *)&endian;
	memcpy(endianPtr+1, &endian1, sizeof(uint32_t));
	memcpy(endianPtr, &endian2, sizeof(uint32_t));

	return endian;
#else
	return value;
#endif
	
}

/*
	Description: 
		allocate object structure memory to node
	Parameters:
		node: the object node needs to allocate memory for object structure
	return:
		return CMS_OK
*/
int cmsXml_NodeAddObject(objectNode_t *node, parameterList_t *list){
	uint32_t object_size = 0;
	uint32_t padding = 0;
	int meta_count = 0, size = 0;
	uint64_t preObjIA = 0;
	uint8_t meta_size, pad_size = 0, pad_type = 0;
	void *ptr, *meta_ptr = NULL;	
	uint32_t type_size =0, attr = 0, config_size = 0, shiftMeta_size = 0;
	parameterList_t *pList = NULL;
	cmsoffset_t node_offset, attr_offset = 0, offset =0, para_offset = 0;
	int configPadOriSize = 0;

	attr = NTOHL(node->attributes);
	if ((node->meta_count == 0)&&(( attr & ATTR_INDEXNODE) != ATTR_INDEXNODE)){
		return CMS_OK;
	}
#if	1	/*add for default value*/		
	/*re-calculate padding again for default value*/
//	refer to cmsXmlAddParameter()
	size = config_size = NTOHL(node->config_size);
	if ((config_size != 0)&&((attr & ATTR_INDEXCHILD) != ATTR_INDEXCHILD)){
		meta_count = NTOHS(node->meta_count);
		ptr = cmsXmlGetObjRealAddr(pdmCB, NTOHDL(node->meta));
		/*check config pad or not*/
		while(meta_count){
			memcpy(&meta_size, ptr, sizeof(uint8_t));
			if (meta_size == PADDING_META_LEN){
				/*this meta is padding meta*/
				/*the fourth byte is padding size*/
				memcpy(&pad_size, (ptr+sizeof(uint8_t)*3), sizeof(uint8_t));
				memcpy(&pad_type, (ptr+sizeof(uint8_t)), sizeof(uint8_t));
				type_size = pad_size;
				if (pad_type == 1){
					//isConfigPadded = 1;
					configPadOriSize = pad_size;
					//padmeta_ptr = ptr;
				}
			}
			else{
				/*get type_size*/
				memcpy(&type_size, (ptr+meta_size-sizeof(uint32_t)), sizeof(uint32_t));
				type_size = NTOHL(type_size);
			}

			size -= (type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
			if (size == 0){
				meta_ptr = ptr + meta_size; /*start of non-config meta*/
				size = -1;
			}
			else if (size < 0){
				shiftMeta_size += meta_size;
			}
			ptr = ptr + meta_size;
			meta_count--;
		}
		/*check padding need modify or not*/
		config_size -= configPadOriSize;
		meta_count = NTOHS(node->meta_count);
		ptr = cmsXmlGetObjRealAddr(pdmCB, NTOHDL(node->meta));
		while(meta_count){
			memcpy(&meta_size, ptr, sizeof(uint8_t));
			if (meta_size != PADDING_META_LEN){
				memcpy(&type_size, (ptr+meta_size-sizeof(uint32_t)), sizeof(uint32_t));
				type_size = NTOHL(type_size);
				type_size &= ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);	
				pList = list;
				while(pList){
					if (!strcmp(pList->name, (ptr+sizeof(uint8_t)))){
						break;
					}
					pList = pList->next;
				}
				if (pList == NULL){
					CMS_LOG(LL_ERROR, "cannot find parameter, it's should be an error, name:%s!!\r\n", (char *)(ptr+sizeof(uint8_t)));
				}
				else{
		
					if (pList->attrValue & PARAMETER_ATTR_DEFAULTVALUE){
						config_size += type_size;	/*double for default value*/
					}
				}		
			}
			ptr = ptr + meta_size;
			meta_count--;		
		}
		/*check padding again after add default value*/
		pad_size = config_size%BYTE_ALIGNS;
		/*re-calculate node's config_size here!!*/
		if (pad_size != 0){
			config_size += BYTE_ALIGNS - pad_size;
			node->config_size = HTONL(config_size);
		}
		else{
			node->config_size = HTONL(config_size);
		}
		if ((configPadOriSize == 0)&&(pad_size != 0)){	/*original no pad, now has pad*/
			pad_size = BYTE_ALIGNS - pad_size;
			/*shift meta data*/
			cmsXml_Malloc(PADDING_META_LEN);
			memmove(meta_ptr + PADDING_META_LEN, meta_ptr, shiftMeta_size);
			/*set padding meta value*/
			offset = 0;
			size = PADDING_META_LEN;
			memcpy(meta_ptr+offset, &size, sizeof(uint8_t));
			offset += sizeof(uint8_t);
			pad_type = 1;
			memcpy(meta_ptr+offset, &pad_type, sizeof(uint8_t));
			offset += sizeof(uint8_t)*2;
			memcpy(meta_ptr+offset, &pad_size, sizeof(uint8_t));
			meta_count = NTOHS(node->meta_count);
			meta_count += 1;
			node->meta_count = HTONS(meta_count);
		}
		else if ((configPadOriSize != 0)&&(pad_size == 0)){	/*original has pad, now no pad*/
			memmove(meta_ptr - PADDING_META_LEN, meta_ptr, shiftMeta_size);
			cmsXml_Free(PADDING_META_LEN);
			meta_count = NTOHS(node->meta_count);
			meta_count -= 1;
			node->meta_count = HTONS(meta_count);	
		}
		else if ((configPadOriSize != 0)&&(pad_size != 0)){	/*original has pad, now has pad*/
			if (configPadOriSize != (BYTE_ALIGNS - pad_size)){	/*pad size is diff*/
				pad_size = BYTE_ALIGNS - pad_size;
				memcpy(meta_ptr - PADDING_META_LEN + sizeof(uint8_t)*3, &pad_size, sizeof(uint8_t));
			}
			/*else: pad size is the same, do nothing*/
			
		}
		/*else: original no pad, now no pad, do nothing*/
	
	}
#endif
	meta_count = NTOHS(node->meta_count);
	ptr = cmsXmlGetObjRealAddr(pdmCB, NTOHDL(node->meta));
	/*get total parameters size*/
	while(meta_count){
		
		memcpy(&meta_size, ptr, sizeof(uint8_t));
		if (meta_size == PADDING_META_LEN){
			memcpy(&pad_size, (ptr+sizeof(uint8_t)*3), sizeof(uint8_t));
			type_size = pad_size;
		}
		else{
			memcpy(&type_size, (ptr+meta_size-sizeof(uint32_t)), sizeof(uint32_t));
			/*remove the first two bits to get the real parameter size*/
			type_size = NTOHL(type_size);
			type_size &= ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);	
			/*write parameter offset here to avoid alignment problem*/
			para_offset = HTONDL(object_size);
			memcpy((ptr+meta_size-(sizeof(uint32_t)+sizeof(cmsoffset_t)*2)), &para_offset, sizeof(cmsoffset_t));
		/*check default parameter or not*/
#if	1	/*add for default value*/	
			pList = list;
			while(pList){
				if (!strcmp(pList->name, (ptr+sizeof(uint8_t)))){
					break;
				}
				pList = pList->next;
			}
			if (pList == NULL){
				CMS_LOG(LL_ERROR, "cannot find parameter, it's should be an error, name:%s!!\r\n", (char *)(ptr+sizeof(uint8_t)));
			}
			else{
		
				if (pList->attrValue & PARAMETER_ATTR_DEFAULTVALUE){
					object_size += type_size;	/*double for default value*/
				}
			}
#endif
		}	
		object_size += type_size;
		ptr = ptr + meta_size;
		meta_count--;
	}
	attr_offset = object_size;

	/*add attribute size*/
	object_size += sizeof(uint32_t)*(NTOHS(node->meta_count));

	/*set attribute offset*/
	meta_count = NTOHS(node->meta_count);
	ptr = cmsXmlGetObjRealAddr(pdmCB, NTOHDL(node->meta));
	
	while(meta_count){
		
		memcpy(&meta_size, ptr, sizeof(uint8_t));
		if (meta_size != PADDING_META_LEN){
			/*set attribute offset*/
			offset = HTONDL(attr_offset);
			memcpy((ptr+meta_size-(sizeof(uint32_t)+sizeof(cmsoffset_t))), &offset, sizeof(cmsoffset_t));

			attr_offset += sizeof(uint32_t);
#if	1	/*add for default attr*/		
			/*check default attribute or not*/
			pList = list;
			while(pList){
				if (!strcmp(pList->name, (ptr+sizeof(uint8_t)))){
					break;
				}
				pList = pList->next;
			}
			if (pList == NULL){
				CMS_LOG(LL_ERROR,"cannot find parameter, it's should be an error, name:%s!!\r\n", (char *)(ptr+sizeof(uint8_t)));
			}
			else{
				if (pList->attrValue & PARAMETER_ATTR_DEFAULTATTR){
					attr_offset += sizeof(uint32_t);	/*double for default attr*/
					object_size += sizeof(uint32_t);
				}	
			}			
#endif
		}
		else{
			/*if padding meta, still need to add padding meta attr size*/
			attr_offset += sizeof(uint32_t);
			object_size += sizeof(uint32_t);
		}
		ptr = ptr + meta_size;
		meta_count--;
	}

	padding = object_size%BYTE_ALIGNS;
	if (padding != 0){
		padding = BYTE_ALIGNS - padding;
	}
	if ((object_size == 0)&& (( attr & ATTR_INDEXNODE) == ATTR_INDEXNODE)){
		/*for index node, add 4 bytes to avoid index node's offset is same with non-object node's offset*/
		/*because index node only allocate memory for node's pointer..., non-object node use node's offset to their object offset*/
		/*the offset are the same if a non-object node follows a index node*/
		padding = BYTE_ALIGNS;
	}
	/*add object padding to 4 bytes*/
#if 1
	/* object size + meta offset + node offset + attribute + next offset + IA. */
	object_size += padding;
	offset = cmsXml_Malloc( object_size + PREOBJ_LEN );
	/* object offset needs to decrease meta offset + node offset + attribute + next offset + IA.*/
	node->object = HTONDL( offset + PREOBJ_LEN );
#else
	offset = cmsXml_Malloc(object_size + sizeof(cmsoffset_t)*count + padding);	/*object size + meta pointer + node pointer + timestamp*/
	node->object = HTONDL(offset + sizeof(cmsoffset_t)*count);	/*object offset needs to decrease meta pointer + node pointer + timestamp*/
#endif
	/* write meta offset to preobj of this prototype object. */
	memcpy(pdmCB->baseaddr + (NTOHDL(node->object) - sizeof(cmsoffset_t)) , &node->meta, sizeof(cmsoffset_t));
	node_offset = HTONDL((cmsoffset_t)node - (cmsoffset_t)pdmCB->baseaddr);
	/* write node offset to preobj of this prototype object. */
	memcpy(pdmCB->baseaddr + (NTOHDL(node->object) - sizeof(cmsoffset_t)*2), &node_offset, sizeof(cmsoffset_t));
#if 1
	/* copy attribute to preobj of this prototype object.*/
	memcpy( pdmCB->baseaddr + ( NTOHDL( node->object ) - PREATTR_LEN ), &node->attributes, sizeof( uint32_t ) );
	/* copy next offset to preobj of this prototype object.*/
	memset( pdmCB->baseaddr + ( NTOHDL( node->object ) - PRENEXT_LEN ), 0, sizeof( cmsoffset_t ) );
	/* initial depth of IA and write IA to preobj of this prototype object.*/
	preObjIA = HTONLL( indexChildDepth );
	memcpy( pdmCB->baseaddr + ( NTOHDL( node->object ) - PREIA_LEN ), &preObjIA, sizeof( uint64_t ) );
#endif
	
	node->object_size = HTONL(object_size);
	
#if 0
	if (attr & ATTR_INDEXCHILD){	/*this node is index child node*/
		cmsXml_IndexChildAddObject(node);
	}		
#endif
	return CMS_OK;
}

/*
	Description: 
		add child node for ix instance index node.
	Parameters:
		middleChildnode: current index node i middle child node.
		curIndexIA: current i instance node instance array.
	return:
*/
static void cmsXml_addChildNodeForPreXML(objectNode_t *middleChildnode, uint64_t curIndexIA)
{
	objectNode_t *tmpNode = middleChildnode, *curNode = NULL;
	cmsoffset_t offset = 0;

	if ( tmpNode != NULL )
	{
		if ( tmpNode->sibling.tree.prev )
		{
			curNode =  (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, tmpNode->sibling.tree.prev);
			cmsXml_addChildNodeForPreXML(curNode, curIndexIA);
		}
 
		if ( tmpNode->sibling.tree.next )
		{
			curNode =  (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, tmpNode->sibling.tree.next);
			cmsXml_addChildNodeForPreXML(curNode, curIndexIA);
		}

		if (( tmpNode->attributes == 0 ) || ( tmpNode->attributes == ATTR_NODECONFIGURED ))
		{
			tmpNode = (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, tmpNode->child);
			if( tmpNode != NULL ){
				if ( tmpNode->sibling.tree.prev )
				{
					curNode =  (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, tmpNode->sibling.tree.prev);
					cmsXml_addChildNodeForPreXML(curNode, curIndexIA);
				}
				if ( tmpNode->sibling.tree.next )
				{
					curNode =  (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, tmpNode->sibling.tree.next);
					cmsXml_addChildNodeForPreXML(curNode, curIndexIA);

				}
			}
		}

		if ( ( tmpNode->attributes & ATTR_OBJECTNODE ) && !( tmpNode->attributes & ATTR_INDEXNODE ) && !( tmpNode->attributes & ATTR_INDEXCHILD ) )
		{
			offset = NTOHDL(tmpNode->name);

			objectNode_t *tmpCurrent = cmsXml_SearchChildNode( pdmCB, middleChildnode, (char *)cmsXmlGetObjRealAddr(pdmCB, offset), NULL );
			cmsXmlAddObjectWithAssignIA( pdmCB, tmpCurrent->object, curIndexIA);

			cmsXml_addChildNodeForPreXML((objectNode_t *)cmsXmlGetObjRealAddr( pdmCB ,tmpCurrent->child), curIndexIA);
		}
	}
}


#ifdef CMS_XML_PARSE_PHASE_1
/*
	Description: 
		compare children of fCurrent if has this node name.
	Parameters:
		name: node's name
	return:
		return CMS_OK
*/
int XMLFilterCompareChild(char *name){
	Xml_object *tmpNode;
	if( fCurrent->children )
	{
		tmpNode = fCurrent->children;
		while( tmpNode )
		{
			if( !stricmp(tmpNode->tag, name) )
			{
				fCurrent = tmpNode;
				return CMS_OK;
			}
			tmpNode = tmpNode->nxt;
		}
	}
	
	return CMS_NOK;
}

/*
	Description: 
		free node attributes memory of Filter tree.
	Parameters:
		xmlAttri: node's attribute value and node's attribute name.
	return:
		no return.
*/
void freeFilterAttributes( Xml_name_value_pair *xmlAttri ) {
	if ( xmlAttri->nxt ) {
		freeFilterAttributes( xmlAttri->nxt );
		xmlAttri->nxt = NULL;
	}
	free(xmlAttri);
}


/*
	Description: 
		free node memory of Filter tree.
	Parameters:
		xmlNode: node of filter tree.
	return:
		no return.
*/
void freeFilterTree( Xml_object *xmlNode ) {
	if ( xmlNode->nxt ) {
		freeFilterTree( xmlNode->nxt );
		xmlNode->nxt = NULL;
	}
	if ( xmlNode->children ) {
		freeFilterTree( xmlNode->children );
		xmlNode->children = NULL;
	}
	if ( xmlNode->attributes ) {
		freeFilterAttributes( xmlNode->attributes );
	}
	free(xmlNode);
}

#endif

#endif

/*
	Description: 
		function used to handle xml start tag ex:<aaa>.
	Parameters:
		udRaw: xml parser expat will give this user data pointer.
		name: xml parser expat will give name pointer.
		attrs: xml parser expat will give this attribute pointer.
	return:
	
*/
static void cms_XmlTagStart (void *udRaw, const char *name, const char **attrs)
{
	userData_t	*ud=udRaw;
	tagNode_t	*stackNode=NULL;
#ifdef 	SYSDEF_PARSER_ON_HOST
	parameterList_t	*paraList;
	objectNode_t *tnode= NULL;
	objParameter_t parameter;
	cmsoffset_t offset = 0;
	char *tmpName;
	uint32_t attr;
#ifdef CMS_XML_PARSE_PHASE_1
	int checkMatchNodeFlag = CMS_NOK;
	cmsoffset_t filterAttr = 0;
#endif
#else
	int skip =0;
	objectNode_t *node = NULL, *tmpCurrent = NULL;
	uint32_t flags;
	int depth = 0;
	uint64_t tmpIA = 0;
	void *ptr = NULL;
#endif
	parentList_t *parentList;
	int		pushstack=1;
	attrList_t *attrList=NULL;
	int paramCont = 1;

	if ( !stricmp( name, "ii" ) ){
		CMS_LOG(LL_ERROR, "parse tag end start ii\n\r");
		skipParameter = 1;
		return;
	}
	
	if(skipParameter == 1){
		CMS_LOG(LL_ERROR, "Skip parameter or node: %s.\n\r", name);
		return;
	}
	
	if(ud->state == StateNodeNotExist)
	{
		nodeNum++;
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		return;
	}
	
	/* Get a tag for this element */
	stackNode=tagPool;
	if(!stackNode){
		/* pool empty, get new tag_node */
		stackNode=(tagNode_t *)malloc(sizeof(tagNode_t));
		if(!stackNode){
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "no memory for stackNode.\n\r");
			return;
		}
		memset(stackNode, 0, sizeof(tagNode_t));
	}
	else
	{
		NODE_DEL(tagPool,stackNode);
	}
	
	if(strlen(name) > CMS_PDM_MAX_NODE_NAME_LEN)
	{
		ud->state=StateError;
		CMS_LOG(LL_ERROR, "XML error at line %d: Tag name is too long.\n\r",XML_GetCurrentLineNumber(parser));
		goto error_handle;
	}
	
	stackNode->prevState=ud->state;
	strcpy(stackNode->name, name);
#if defined(SYSDEF_PARSER_ON_HOST)
	if ( !stricmp( name, "i" ) )
		indexChildDepth++;
#endif

	switch(ud->state){
	case StateSetting:	
		/* Add all the attributes */
		attrList=(struct attrList_s *)malloc(sizeof(struct attrList_s));
		memset(attrList, 0, sizeof(struct attrList_s));
#ifdef SYSDEF_PARSER_ON_HOST
		if(cms_GetAttrValue(attrs, attrList)!=0)
#else	
		if(cms_GetAttrValue2(attrs, attrList)!=0)
#endif
		{
			ud->state=StateError;
			goto error_handle;
		}
		

#ifndef SYSDEF_PARSER_ON_HOST //RUNTIME_PARSE
		if(attrList->paraFlag)//parameter
		{
			if ((ud->configCurrent->attributes & ATTR_OBJECTNODE) != ATTR_OBJECTNODE)
			{
				CMS_LOG(LL_ERROR, "This parameter has been removed, skip it!! \"%s\"\n\r", name);
				
				ud->state=StateNodeNotExist;
				nodeNum++;
				goto error_handle;
			}
			ud->parameterNamePtr=malloc(CMS_PDM_MAX_NODE_NAME_LEN);

			flags = cmsXml_getParameterAttr( pdmCB, ud->currentOffset, (char *)name );
			if(flags == 0){//the configed parameter is not exist
				//ud->contentFlag = 0;
				/*compatible with one situation: parameter configed attr in current xml, but this parameter in upgrade fw is nonconfiged;
				nonconfiged parameter attr is 0*/
				//goto error_handle;  
				paramCont = 0;
			}

			flags &= PARAMETER_ATTR_FIX_BITS;	/*remove attr except fix bits*/
			attrList->attrValue &= ~PARAMETER_ATTR_FIX_BITS;	/*remove fix bits attr*/
			flags |= attrList->attrValue;

			cmsXml_setParameterAttr( pdmCB, ud->currentOffset, (char *)name, flags, 1 );

			strcpy(ud->parameterNamePtr, name);
			stackNode->parameterFlag = 1;
			ud->checkContentFlag = 1;
			ud->nodeToParaFlag = 1;
		}else{
			node = (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, ud->parentList->node->child);
			/*if there is only one node and it's removed at new f/w, crash here!!*/
			if (node == NULL){
				ud->state=StateNodeNotExist;
				nodeNum++;
				CMS_LOG(LL_ERROR, "cmsXml_SearchChildNode \"%s\" fail.\n\r", name);
				goto error_handle;
			}

			if (((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD)&&(*(name+1) != '\0'))
				skip = 1;

			/* find prototype node and check this index object is existed or not. */
			/* if this index object doesn't existed, create it and set the value. */
			if ( skip == 1 )
			{
				/* get prototype node. */
				tmpCurrent = cmsXml_SearchChildNode( pdmCB, node, "i", NULL );
				if ( tmpCurrent == NULL )
				{
					ud->state = StateError;
					CMS_LOG(LL_ERROR, "XML error at line %d: cmsXml_GetObjectByOID return NULL.\n\r", XML_GetCurrentLineNumber( parser ) );
					goto error_handle;
				}
				depth = cmsXmlGetIADepth( cmsXmlGetPreObjIA( pdmCB, tmpCurrent->object ) );

				/* setup IA by depth and index number. */
				if ( atoi( name + 1 ) )
				{
					tmpIA = cmsXmlSetIAValue( ud->currentIA, depth, atoi( name + 1 ) );
					tmpIA = cmsXmlSetIAValue( tmpIA, IA_DEPTHNUM, depth );
				}
				else
				{
					//ud->state = StateError;
					CMS_LOG(LL_ERROR, "XML error at line %d: config.xml doesn't support <ii> index object node.\n\r", XML_GetCurrentLineNumber( parser ) );
					//goto error_handle;
					break;
				}
				ud->currentIA = tmpIA;

				/* test this index object is existed or not. if not existed, create this index object. */
				ptr = cmsXml_GetObjectByOID( pdmCB, cmsXml_GetOIDByOffset( pdmCB, tmpCurrent->object ), ud->currentIA, ADD_IF_NOT_EXISTED );
				if ( ptr == NULL )
				{
					ud->state = StateError;
					CMS_LOG(LL_ERROR, "XML error at line %d: cmsXml_GetObjectByOID return NULL.\n\r", XML_GetCurrentLineNumber( parser ) );
					goto error_handle;
				}
				else
				{
					ud->currentOffset = cmsXmlGetPtrOffset( pdmCB, ptr );
				}
 				//configuration saving, set the offset to instance object's offset
				cmsXml_getFullPathByID(pdmCB, tmpCurrent->object);
			}
			else
			{
				tmpCurrent = cmsXml_SearchChildNode( pdmCB, node, (char *)name, NULL );
				if(tmpCurrent==NULL){
					ud->state=StateNodeNotExist;
					nodeNum++;
					CMS_LOG(LL_ERROR,"No this node,cmsXml_SearchChildNode failed, skip it!! \"%s\"\n\r",name);
					goto error_handle;
				}
				ud->currentOffset = tmpCurrent->object;

				if ( ud->currentIA && ( tmpCurrent->attributes & ATTR_OBJECTNODE ) )
				{
					/* test this index object is existed or not. if not existed, create this index object. */
					ptr = cmsXml_GetObjectByOID( pdmCB, cmsXml_GetOIDByOffset( pdmCB, tmpCurrent->object ), ud->currentIA, ADD_IF_NOT_EXISTED );
					if ( ptr == NULL )
					{
						ud->state = StateError;
						CMS_LOG(LL_ERROR, "XML error at line %d: cmsXml_GetObjectByOID return NULL.\n\r", XML_GetCurrentLineNumber( parser ) );
						goto error_handle;
					}
					else
					{
						ud->currentOffset = cmsXmlGetPtrOffset( pdmCB, ptr );
					}
				}
			}

			ud->configCurrent = tmpCurrent;
			/*mark node is configured if the node is at config.xml*/
			ud->configCurrent->attributes |= ATTR_NODECONFIGURED;
			cmsXml_setNodeStatus(pdmCB, ud->configCurrent, 1);
			stackNode->parameterFlag = 0;
			ud->checkContentFlag = 0;
			ud->nodeToParaFlag = 0;
		}	
#else	//xml parse process
		if (skipIndexChild > 0){
			/*skipIndexChild > 0, skip parse, skipIndexChild++*/
			skipIndexChild++;
			break;
		}
		if((ud->nodeToParaFlag == 1) && (attrList->paraFlag == 0))
		{
			if(cms_setParameter(ud) == CMS_NOK)
			{
				ud->state=StateError;
				break;
			}
		}
		if(attrList->paraFlag)//parameter
		{
			if(checkNode)
			{
				ud->state=StateError;
				CMS_LOG(LL_ERROR, "XML error at line %d: Parameter must arrange before node.\n\r",XML_GetCurrentLineNumber(parser));
				goto error_handle;
			}
			parameter.name = (char *)name;
			parameter.type = attrList->type;
			parameter.len = attrList->length;
			parameter.config = attrList->configFlag;
			switch (parameter.type){
			case PARAMETER_TYPE_UINT8:
			case PARAMETER_TYPE_BOOLEAN:
				parameter.max.unsign.u8 = (uint8_t)attrList->maxValue;
				parameter.min.unsign.u8 = (uint8_t)attrList->minValue;
				break;
			case PARAMETER_TYPE_UINT16:
				parameter.max.unsign.u16 = HTONS((uint16_t)attrList->maxValue);
				parameter.min.unsign.u16 = HTONS((uint16_t)attrList->minValue);
				break;
			case PARAMETER_TYPE_UINT32:
				parameter.max.unsign.u32 = HTONL((uint32_t)attrList->maxValue);
				parameter.min.unsign.u32 = HTONL((uint32_t)attrList->minValue);
				break;
			case PARAMETER_TYPE_UINT64:
				parameter.max.unsign.u64 = cms_transForm64Endian(attrList->maxValue);
				parameter.min.unsign.u64 = cms_transForm64Endian(attrList->minValue);
				break;
			case PARAMETER_TYPE_SINT7:
				parameter.max.sign.s7 = (int8_t)attrList->maxValue;
				parameter.min.sign.s7 = (int8_t)attrList->minValue;				
				break;
			case PARAMETER_TYPE_SINT15:
				parameter.max.sign.s15 = HTONS((int16_t)attrList->maxValue);
				parameter.min.sign.s15 = HTONS((int16_t)attrList->minValue);	
				break;
			case PARAMETER_TYPE_SINT31:
				parameter.max.sign.s31 = HTONL((int32_t)attrList->maxValue);
				parameter.min.sign.s31 = HTONL((int32_t)attrList->minValue);
				break;
			case PARAMETER_TYPE_SINT63:
				parameter.max.sign.s63 = cms_transForm64Endian(attrList->maxValue);
				parameter.min.sign.s63 = cms_transForm64Endian(attrList->minValue);	
				break;
			default:
				break;
			}
			cmsXml_addParameter(ud->configCurrent, &parameter);//Need to be fixed
			paraList=(struct parameterList_s *)malloc(sizeof(struct parameterList_s));
			memset(paraList, 0, sizeof(struct parameterList_s));
			paraList->attrValue = attrList->attrValue;
			paraList->type = attrList->type;
			paraList->maxValue = attrList->maxValue;
			paraList->minValue = attrList->minValue;
			paraList->name = malloc(CMS_PDM_MAX_NODE_NAME_LEN);
			strcpy(paraList->name, name);
			stackNode->parameterFlag = 1;
			ud->parameterNum++;
			ud->nodeToParaFlag = 1;
			paraList->next=ud->parameterList;
			ud->parameterList=paraList;
			ud->checkContentFlag = 1;
			
			/*add for default attr*/
			attr = NTOHL(ud->configCurrent->attributes);
			if ((attr & ATTR_INDEXCHILD) != ATTR_INDEXCHILD){
				/*if the parameter has attribute except PARAMETER_ATTR_READONLY and PARAMETER_ATTR_CONFIG*/
				/*only for config parameter, because config parameters would save to config.xml*/
				if (((paraList->attrValue & ~PARAMETER_ATTR_FIX_BITS) != 0)&&((paraList->attrValue & PARAMETER_ATTR_CONFIG)==PARAMETER_ATTR_CONFIG)){
					paraList->attrValue |= PARAMETER_ATTR_DEFAULTATTR;
				}
			}
		}
		else
		{//node
			checkNode = 0;
			if (indexChildNumCheck == 1){
				if (attrList->nodeNumber == 0){
					skipIndexChild = 1;		/*node number is 0, skip all objects until the index child is end*/
					break;	/*return?!*/
				}
				else{
					indexChildNumCheck = 0;
				}
			}

#ifdef CMS_XML_PARSE_PHASE_1
			if( filterXmlFlag ) {
				attr = NTOHL(ud->configCurrent->attributes); // get parent's attribute.
				if( attr & ATTR_FILTERMATCHNODE )
				{
					checkMatchNodeFlag = XMLFilterCompareChild((char *)name);
					if( checkMatchNodeFlag == CMS_OK )
					{
						filterAttr = 0; // for store indexchild->attribute.
						filterAttr |= ATTR_FILTERMATCHNODE;
						if( fCurrent->attributes )
						{
							if( !stricmp(fCurrent->attributes->name, "EVERYNODE") ) filterAttr |= ATTR_FILTEREVERYNODE;
							if( !stricmp(fCurrent->attributes->name, "MAXNODENUMBER") ) filterAttr |= ATTR_FILTERONLYNODE;
						}
					}
				}
			}
#endif
			if(attrList->nodeNumber >0){//index node, alloc mem and link parent node
#ifdef CMS_XML_PARSE_PHASE_1
				if( checkMatchNodeFlag == CMS_OK )
				{
					ud->configCurrent = cmsXml_LinkIndexChild(ud->configCurrent, attrList->nodeNumber, filterAttr);
				}
				else
				{
					ud->configCurrent = cmsXml_LinkIndexChild(ud->configCurrent, attrList->nodeNumber, 0);
				}
#else
				ud->configCurrent = cmsXml_LinkIndexChild(ud->configCurrent, attrList->nodeNumber, 0);
#endif
				cmsXml_NodeAddObject(ud->configCurrent, NULL);
			}else{//object node, alloc mem and link parent node
				if(!(tnode = cmsXml_NewNode()))
				{
					ud->state=StateError;
					CMS_LOG(LL_ERROR, "cmsXml_NewNode fail.\n\r");
					break;
				}
				cmsXml_SetNodeName(tnode, (char *)name);
				cmsXml_LinkChildNode(ud->configCurrent, tnode);
				offset = cmsXmlGetPtrOffset(pdmCB, ud->configCurrent);
				tnode->parent = HTONDL(offset);
				cmsXml_LinkSiblingNode(ud->configCurrent, tnode);
				ud->configCurrent=tnode;
			}
			tmpName=cmsXmlGetObjRealAddr(pdmCB, NTOHDL(ud->configCurrent->name));
			if(tmpName != NULL){
				if(stricmp("i",tmpName) == 0 && attrList->nodeNumber == 0)
				{
					ud->state=StateError;
					CMS_LOG(LL_ERROR, "XML error at line %d: \"i\" node must have \"MAXNODENUMBER\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
					break;
				}
			}
			attr = NTOHL(ud->configCurrent->attributes);
			if(attrList->attrValue & ATTR_INDEXNODE){
				attr |= ATTR_INDEXNODE;
				indexChildNumCheck = 1;
			}
			if(attrList->attrValue & ATTR_WRITABLE){
				attr |= ATTR_WRITABLE;
			}
			if(attrList->attrValue & ATTR_HIDEFROMACS){
				attr |= ATTR_HIDEFROMACS;
			}
			if(attrList->attrValue & ATTR_NO_STORABLE){
				attr |= ATTR_NO_STORABLE;
			}
			if(attrList->updateObjFlag == 1){
				ud->configCurrent->updateObjFlag = 1;
			}else{
				ud->configCurrent->updateObjFlag = 0;
			}

#ifdef CMS_XML_PARSE_PHASE_1
			if( checkMatchNodeFlag == CMS_OK ) attr |= ATTR_FILTERMATCHNODE;
#endif
			ud->configCurrent->attributes = HTONL(attr);
			ud->configCurrent->priority = attrList->priValue;

			stackNode->parameterFlag = 0;
			ud->nodeToParaFlag = 0;
			ud->checkContentFlag = 0;
		}
#endif
		if(attrList->paraFlag == 0)
		{
			parentList=(struct parentList_s *)malloc(sizeof(struct parentList_s));
			parentList->node = ud->configCurrent;
			parentList->next=ud->parentList;	
			ud->parentList=parentList;
#ifdef SYSDEF_PARSER_ON_HOST			
			if(attrList->nodeNumber >0){
				attr = NTOHL(parentList->next->node->attributes);
				if(!(attr & ATTR_INDEXNODE))
				{
					ud->state=StateError;
					CMS_LOG(LL_ERROR, "XML error at line %d: This node has \"MAXNODENUMBER\" attribute, but it's parent node doesn't have \"INDEXNODE\" attribute.\n\r",XML_GetCurrentLineNumber(parser));
					break;
				}
			}
#endif			
		}
		/* Setup the content pointers */
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		if(paramCont == 1)
			ud->contentFlag=1;
		else
			ud->contentFlag=0;
		free(attrList);
		break;
	case StateDone:
	case StateError:
		pushstack=0;
		errorflag = CMS_NOK;
		goto error_handle;
	case StateUnknown:
		break;
	case StateStart:		
#ifndef SYSDEF_PARSER_ON_HOST //RUNTIME_PARSE
		if(!(ud->configHead = 	cmsXml_SearchChildNode(pdmCB, pdmCB->rootNode, (char *)name,NULL)))
		{
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "cmsXml_SearchChildNode \"%s\" fail.\n\r", name);
			break;
		}
		ud->configCurrent= ud->configHead;
		ud->configCurrent->attributes |= ATTR_NODECONFIGURED;
		cmsXml_setNodeStatus(pdmCB, ud->configCurrent, 1);
		ud->currentOffset = ud->configCurrent->object;
#else
		if(!(tnode = cmsXml_NewNode()))
		{
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "cmsXml_NewNode fail.\n\r");
			break;
		}
		ud->configHead=tnode;
		ud->configCurrent=tnode;
		ud->configCurrent->priority = 50;
		cmsXml_SetNodeName(tnode, (char *)name);

#ifdef CMS_XML_PARSE_PHASE_1
		if( filterXmlFlag ) {
			if( fCurrent->children ) // Because XML_Parse Lib doesn't know <?declare?> tag.
			{
				fCurrent = fCurrent->children; // To skip declare in first line.
				if( !stricmp(fCurrent->tag, name) )
				{
					attr = NTOHL(ud->configCurrent->attributes);
					attr |= ATTR_FILTERMATCHNODE;
					ud->configCurrent->attributes = HTONL(attr);
				}
			}
		}
#endif
#endif
		stackNode->parameterFlag = 0;
		parentList=(struct parentList_s *)malloc(sizeof(struct parentList_s));
		parentList->node = ud->configCurrent;
		parentList->next=ud->parentList;	
		ud->parentList=parentList;
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->contentFlag=1;
		ud->state=StateSetting;
		break;
	default:
		ud->state=StateError;
		pushstack=0;
		break;
	}

	if(pushstack)
	{
		NODE_ADD(ud->tagStack, stackNode);
	}
	else
	{
		NODE_ADD(tagPool, stackNode);
	}
	return;
error_handle:
	if (attrList)
		free(attrList);
	return;
}

/*
	Description: 
		function used to handle xml start tag ex:<aaa>.
	Parameters:
		udRaw: xml parser expat will give this user data pointer.
		name: xml parser expat will give name pointer.
		attrs: xml parser expat will give this attribute pointer.
	return:
	
*/
static void cmsXml_PredefTagStart (void *udRaw, const char *name, const char **attrs)
{
	userData_t	*ud=udRaw;
	tagNode_t	*stackNode=NULL;
	int skip =0;
	objectNode_t *node = NULL, *tmpCurrent = NULL;
	uint32_t flags;
	parentList_t *parentList;
	int		pushstack=1;
	attrList_t *attrList=NULL;
	uint32_t attr;
#if defined(SYSDEF_PARSER_ON_HOST)
	int depth = 0;
	uint64_t tmpIA = 0;
#endif

	if(ud->state == StateNodeNotExist)
	{
		nodeNum++;
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		return;
	}
	/* Get a tag for this element */
	stackNode=tagPool;
	if(!stackNode){
		/* pool empty, get new tag_node */
		stackNode=(tagNode_t *)malloc(sizeof(tagNode_t));
		if(!stackNode){
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "no memory for stackNode.\n\r");
			return;
		}
		memset(stackNode, 0, sizeof(tagNode_t));
	}
	else
	{
		NODE_DEL(tagPool,stackNode);
	}
	
	if(strlen(name) > CMS_PDM_MAX_NODE_NAME_LEN)
	{
		ud->state=StateError;
		CMS_LOG(LL_ERROR, "XML error at line %d: Tag name is too long.\n\r",XML_GetCurrentLineNumber(parser));
		goto error_handle;
	}
	
	stackNode->prevState=ud->state;
	strcpy(stackNode->name, name);
	switch(ud->state){
	case StateSetting:	
		/* Add all the attributes */
		attrList=(struct attrList_s *)malloc(sizeof(struct attrList_s));
		memset(attrList, 0, sizeof(struct attrList_s));
		if(cms_GetAttrValue2(attrs, attrList)!=0){
			goto error_handle;
		}
		if(attrList->paraFlag)//parameter
		{
			ud->parameterNamePtr=malloc(CMS_PDM_MAX_NODE_NAME_LEN);
#if defined(SYSDEF_PARSER_ON_HOST)
			flags = cmsXml_getParameterAttr( pdmCB, ud->currentOffset, (char *)name );
#else
			flags = cmsXml_getParameterAttr(pdmCB, ud->configCurrent->object, (char *)name);
#endif
			if(NTOHL(attrList->attrValue) & PARAMETER_ATTR_ACTIVENOTIFY)
				flags |= PARAMETER_ATTR_ACTIVENOTIFY;
			else if(NTOHL(attrList->attrValue) & PARAMETER_ATTR_PASSIVENOTIFY)
				flags |= PARAMETER_ATTR_PASSIVENOTIFY;
			else
			{
				flags &=~ PARAMETER_ATTR_ACTIVENOTIFY;
				flags &=~ PARAMETER_ATTR_PASSIVENOTIFY;
			}
#if defined(SYSDEF_PARSER_ON_HOST)
			cmsXml_setParameterAttr( pdmCB, ud->currentOffset, (char *)name, flags, 1 );
#else
			cmsXml_setParameterAttr(pdmCB, ud->configCurrent->object, (char *)name, flags, 1);
#endif
			strcpy(ud->parameterNamePtr, name);
			stackNode->parameterFlag = 1;
			ud->checkContentFlag = 1;
		}else{
			node = (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, NTOHDL(ud->parentList->node->child));
			if (((NTOHL(node->attributes) & ATTR_INDEXCHILD) == ATTR_INDEXCHILD)&&(*(name+1) != '\0')){
				skip = 1;
			}
#if defined(SYSDEF_PARSER_ON_HOST)
			/* change to find prototype and check this index child node is existed or not. */
			/* if this node not existed, create it and set the value. */
			if ( skip == 1 )
			{
				/* get prototype node. */
				tmpCurrent = cmsXml_SearchChildNode( pdmCB, node, "i", NULL );
				if(tmpCurrent==NULL){
					ud->state=StateError;
					nodeNum++;
					CMS_LOG(LL_ERROR, "No proto node of node %s, cmsXml_SearchChildNode failed!\n\r", name);
					goto error_handle;
				}
				if(atoi(name+1) > tmpCurrent->sibling.child_count){
					ud->state=StateError;
					CMS_LOG(LL_ERROR, "index num(%s) excced the max num(%d), error at line %d!\n\r", name,  tmpCurrent->sibling.child_count,  XML_GetCurrentLineNumber(parser));
					goto error_handle;
				}
				tmpIA = NTOHLL( cmsXmlGetPreObjIA( pdmCB, NTOHL( tmpCurrent->object ) ) );
				depth = cmsXmlGetIADepth( tmpIA );

				/* setup IA by depth and index number. */
				if ( atoi( name + 1 ) )
				{
					tmpIA = cmsXmlSetIAValue( ud->currentIA, depth, atoi( name + 1 ) );
					tmpIA = cmsXmlSetIAValue( tmpIA, IA_DEPTHNUM, depth );
				}
				ud->currentIA = tmpIA;

				/* test this index child object is existed or not. if not existed, create this index child object. */
				/* input offset is network type; output offset is network type. */
				ud->currentOffset = cmsXmlAddObjectWithAssignIA( pdmCB, tmpCurrent->object, ud->currentIA );

				cmsXml_addChildNodeForPreXML((objectNode_t *)cmsXmlGetObjRealAddr( pdmCB ,tmpCurrent->child), ud->currentIA );
			}
			else
			{
				tmpCurrent = cmsXml_SearchChildNode( pdmCB, node, (char *)name, NULL );
				if(tmpCurrent==NULL){
					ud->state=StateError;
					nodeNum++;
					CMS_LOG(LL_ERROR, "No node %s at line %d, cmsXml_SearchChildNode failed!\n\r", name, XML_GetCurrentLineNumber(parser));
					goto error_handle;
				}
				ud->currentOffset = tmpCurrent->object;

				/* point to prototype node, IA should not have value. */
				if ( ( *name == 'i' ) && ( strlen( name ) == 1 ) && ud->currentIA )
				{
					ud->state = StateError;
					CMS_LOG(LL_ERROR, "cmsXml_PredefTagStart \"%s\" fail.\n\r", name );
					break;
				}
				else if ( ud->currentIA && ( NTOHL( tmpCurrent->attributes ) & ATTR_OBJECTNODE ) )
				{
					/* test this index child object is existed or not. if not existed, create this index child object. */
					ud->currentOffset = cmsXmlAddObjectWithAssignIA( pdmCB, tmpCurrent->object, ud->currentIA );
				}
			}
#else
			if(!( tmpCurrent = cmsXml_SearchChildNode(pdmCB, node, (char *)(name + skip), NULL)))
			{
				ud->state=StateNodeNotExist;
				nodeNum++;
				CMS_LOG(LL_ERROR, "cmsXml_SearchChildNode \"%s\" fail.\n\r", name);
				goto error_handle;
			}
#endif
			/*if the ACTIVENODE is set for the node, mark the node ALWAYSACTIVE for tr069*/
			if ((attrList->attrValue & ATTR_ALWAYSACTIVE) == ATTR_ALWAYSACTIVE){
#if defined(SYSDEF_PARSER_ON_HOST)
				attr = NTOHL( tmpCurrent->attributes ) | ATTR_NODECONFIGURED;
				tmpCurrent->attributes = HTONL( attr );
				attr |= ATTR_ALWAYSACTIVE;
				cmsXml_SetPreObjAttr( pdmCB, NTOHL( ud->currentOffset ), HTONL( attr ) );
#else
				attr = NTOHL(tmpCurrent->attributes) | ATTR_ALWAYSACTIVE;
				attr |= ATTR_NODECONFIGURED;
				tmpCurrent->attributes = HTONL(attr);
#endif
			}
			ud->configCurrent = tmpCurrent;
			stackNode->parameterFlag = 0;
			ud->checkContentFlag = 0;
		}	
		if(attrList->paraFlag == 0)
		{
			parentList=(struct parentList_s *)malloc(sizeof(struct parentList_s));
			parentList->node = ud->configCurrent;
			parentList->next=ud->parentList;	
			ud->parentList=parentList;		
		}
		/* Setup the content pointers */
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->contentFlag=1;
		free(attrList);
		break;
	case StateDone:
	case StateError:
		pushstack=0;
		errorflag = CMS_NOK;
		goto error_handle;
	case StateUnknown:
		break;
	case StateStart:
		if(!(ud->configHead = 	cmsXml_SearchChildNode(pdmCB, pdmCB->rootNode, (char *)name,NULL)))
		{
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "cmsXml_SearchChildNode \"%s\" fail.\n\r", name);
			break;
		}
		ud->configCurrent= ud->configHead;
#ifdef SYSDEF_PARSER_ON_HOST
		ud->currentOffset = ud->configCurrent->object;
#endif
		stackNode->parameterFlag = 0;
		parentList=(struct parentList_s *)malloc(sizeof(struct parentList_s));
		parentList->node = ud->configCurrent;
		parentList->next=ud->parentList;	
		ud->parentList=parentList;
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->contentFlag=1;
		ud->state=StateSetting;
		break;
	default:
		ud->state=StateError;
		pushstack=0;
		break;
	}

	if(pushstack)
	{
		NODE_ADD(ud->tagStack, stackNode);
	}
	else
	{
		NODE_ADD(tagPool, stackNode);
	}
	return;
error_handle:
	if (attrList)
		free(attrList);
	return;
}

/*
	Description: 
		function used to handle xml end tag ex:</aaa>.
	Parameters:
		udRaw: xml parser expat will give this user data pointer.
		name: xml parser expat will give name pointer.
	return:
	
*/
static void cmsXml_TagEnd(void *udRaw, const char *name)
{
	userData_t *ud = udRaw;
	tagNode_t *stackNode;
#ifdef SYSDEF_PARSER_ON_HOST
	parentList_t	*parentList;
	uint32_t attr;
#else
	uint32_t type = 0;
	char *param_pp[3];
	int ret = 0;
	int depth = 0;
	uint64_t tmpIA = 0;
#endif
	parentList_t *tempParentList = NULL;

	if ( !stricmp( name, "ii" ) ){
		CMS_LOG(LL_ERROR, "parse tag end for ii\n\r");
		skipParameter = 0;
		return;
	}
	if(skipParameter == 1){
		CMS_LOG(LL_ERROR, "Skip parameter or node: %s.\n\r", name);
		return;
	}

	if(ud->state == StateNodeNotExist)
	{
		nodeNum--;
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		if(nodeNum == 0)
			ud->state=StateSetting;
		return;
	}
	stackNode=ud->tagStack;
	if(!stackNode){
		CMS_LOG(LL_ERROR, "No tag node.\n\r");
		ud->state=StateError;
		errorflag = CMS_NOK;
		return;
	}
	switch(ud->state)
	{
	case StateError:
		return;
	case StateSetting:
		if(!ud->configHead)
		{
			CMS_LOG(LL_ERROR, "Lost head node.\n\r");
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}
		if(!ud->configCurrent)
		{
			CMS_LOG(LL_ERROR, "Lost current node.\n\r");
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}
//RUNTIME_PARSE
#ifndef SYSDEF_PARSER_ON_HOST
		if(ud->contentFlag != 0){
			if ((ud->nodeToParaFlag == 1) && (ud->parameterNamePtr != NULL)){
				if(ud->text != NULL){
					type = PARAMETER_TYPE_STRING;
					
					param_pp[0] = ud->parameterNamePtr;
					param_pp[1] = ud->text;
					param_pp[2] = (char *)&type ;
				
					ret = cmsXml_setParameter( pdmCB, ud->currentOffset, 1, param_pp);
					
					free(ud->parameterNamePtr);
					ud->parameterNamePtr=NULL;

					if(ret == CMS_NOK)
					{
						ud->state=StateError;
						errorflag = CMS_NOK;
						break;
					}
				}else{
					/*Fix Bug: when string type set "" NULL string in current xml, then reboot, the value is not NULL, but same with sysdef.xml*/
					uint32_t valueType = cmsXml_getParaValueType(pdmCB, ud->currentOffset, ud->parameterNamePtr);
					if(valueType == PARAMETER_TYPE_STRING){
						param_pp[0] = ud->parameterNamePtr;
						param_pp[1] = "\0";
						param_pp[2] = (char *)&valueType ;
						
						ret = cmsXml_setParameter( pdmCB, ud->currentOffset, 1, param_pp);
						
						free(ud->parameterNamePtr);
						ud->parameterNamePtr=NULL;

						if(ret == CMS_NOK)
						{
							ud->state=StateError;
							errorflag = CMS_NOK;
							break;
						}
					}
				}
			}
			else{
				/*the node has no parameters, reset the node status*/
				//cmsXml_setNodeStatus(pdmCB, ud->configCurrent, 0);
			}
		}
#else
		if (skipIndexChild > 1){
			/*if skipIndexChild > 1, it means it's not index child's end, decrease skipIndexChild*/
			skipIndexChild--;
			break;
		}
		else if (skipIndexChild == 1){
			/*if skipIndexChild is 1, it means this is index child's end tag, reset flags*/
			skipIndexChild = 0;
			indexChildNumCheck = 0;
			ud->checkContentFlag = 1;	/*skip checking*/
			break;
		}
		if(ud->checkContentFlag == 0)
		{
			CMS_LOG(LL_ERROR, "XML error at line %d: This node doesn't have parameter.\n\r",XML_GetCurrentLineNumber(parser));
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}

		attr = NTOHL(ud->configCurrent->attributes);

#ifdef CMS_XML_PARSE_PHASE_1
		if( filterXmlFlag ) {
			if( attr & ATTR_FILTERMATCHNODE )
			{
				if( !stricmp(fCurrent->tag, name) ) fCurrent = fCurrent->parent;
			}
			if( fCurrent == rootFilter ) freeFilterTree( rootFilter );
		}
#endif
		if((attr & ATTR_INDEXCHILD)&&(stackNode->parameterFlag == 0))
		{	
			parentList=ud->parentList;
			if(parentList->next){
				cmsXml_IndexChildCopyNode(ud->configCurrent, parentList->next);
			}
		}
		//make sure no content
		if((ud->contentFlag!=0)&&(ud->parameterList != NULL) && (ud->text!=NULL))
		{
			ud->parameterList->value = malloc(ud->textlen);
			memcpy(ud->parameterList->value, ud->text, ud->textlen);
#if	1	/*add for default value*/			
			/*if value is existed, add default value at RDM*/
			if (((attr & ATTR_INDEXCHILD) != ATTR_INDEXCHILD)&&((ud->parameterList->attrValue & PARAMETER_ATTR_CONFIG) == PARAMETER_ATTR_CONFIG)&&((ud->textlen > 2)||((ud->textlen == 2)&&(*ud->text != '0')))){
				ud->parameterList->attrValue |= PARAMETER_ATTR_DEFAULTVALUE;
			}
#endif			
		}
		if((ud->nodeToParaFlag == 1) && (stackNode->parameterFlag == 0))
		{
			if(cms_setParameter(ud) == CMS_NOK)
			{
				ud->state=StateError;
				errorflag = CMS_NOK;
				break;
			}
		}
		else if( attr & ATTR_INDEXNODE)
		{//Index node is an exception of object node
			parentList=ud->parentList;
			cmsXml_NodeAddObject(ud->configCurrent, NULL);
			cmsXml_regObjectId(ud->configCurrent, parentList->next);
		}
		else if ((stackNode->parameterFlag == 0)&&((attr & ATTR_OBJECTNODE) != ATTR_OBJECTNODE))
		{
			/*for object change list, we register node's offset to cmsXml_obj_id.h*/
			parentList=ud->parentList;
			cmsXml_regObjectId(ud->configCurrent, parentList->next);
		}
#endif
		if(stackNode->parameterFlag == 0){
#if !defined(SYSDEF_PARSER_ON_HOST)
			/* if currentIA is not 0, get this object offset before assign new value. */
			depth = cmsXmlGetIADepth( ud->currentIA );
			if ( ( *name == 'i' ) && atoi( name + 1 ) )
			{
				tmpIA = cmsXmlSetIAValue( ud->currentIA, depth, 0 );
				tmpIA = cmsXmlSetIAValue( tmpIA, IA_DEPTHNUM, depth - 1 );
				ud->currentIA = tmpIA;
			}
#endif
			checkNode = 1;
			ud->nodeToParaFlag = 0;
			if(ud->parentList && ud->parentList->next!=NULL)
				ud->configCurrent = ud->parentList->next->node;

			if(ud->parentList != NULL){
				if(ud->parentList->next != NULL)
					tempParentList = ud->parentList->next;
				free(ud->parentList);
				ud->parentList = NULL;
				ud->parentList=tempParentList;
			}
		}
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->textlen=0;
		ud->contentFlag=0;
#if defined(SYSDEF_PARSER_ON_HOST)
		if ( !stricmp( name, "i" ) )
			indexChildDepth--;
#endif
		break;
	}
	/* This if statement should never be true. The xml lib has internal
	 * checking for this */
	if( stricmp(name, (const char*) stackNode->name))
	{
		CMS_LOG(LL_ERROR|LL_SYSLOG, "Closing nodes don't match up name:%s, stackNode->name:%s\n\r", name, stackNode->name);
		ud->state=StateError;
		errorflag = CMS_NOK;
		return;
	}
	NODE_DEL(ud->tagStack, stackNode);
	ud->state=stackNode->prevState;
	NODE_ADD(tagPool, stackNode);
	return;
}

/*
	Description: 
		function used to handle xml end tag ex:</aaa>.
	Parameters:
		udRaw: xml parser expat will give this user data pointer.
		name: xml parser expat will give name pointer.
	return:
	
*/
static void cmsXml_PredefTagEnd(void *udRaw, const char *name)
{
	userData_t *ud = udRaw;
	tagNode_t *stackNode;
	uint32_t type = 0, *type_p;
	char **tempParameterPtr;
	char *parameter;
	int ret = 0;
	parentList_t *tempParentList = NULL;
	uint32_t attr = 0;
#if 0
	uint32_t childCount = 0;
#endif
	char *tmpName = NULL;
#if defined(SYSDEF_PARSER_ON_HOST)
	int depth = 0;
	uint64_t tmpIA = 0;
#endif

	if(ud->state == StateNodeNotExist)
	{
		nodeNum--;
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		if(nodeNum == 0)
			ud->state=StateSetting;
		return;
	}
	stackNode=ud->tagStack;
	if(!stackNode){
		CMS_LOG(LL_ERROR, "No tag node.\n\r");
		ud->state=StateError;
		errorflag = CMS_NOK;
		return;
	}
	switch(ud->state)
	{
	case StateError:
		return;
	case StateSetting:
		if(!ud->configHead)
		{
			CMS_LOG(LL_ERROR, "Lost head node.\n\r");
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}
		if(!ud->configCurrent)
		{
			CMS_LOG(LL_ERROR, "Lost current node.\n\r");
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}

		if(ud->contentFlag != 0){
			parameter=malloc(sizeof(void*)*3);
			tempParameterPtr = (char **)parameter;
			memcpy(parameter, &ud->parameterNamePtr, sizeof(void*));
			parameter+= sizeof(void*);
			memcpy(parameter, &ud->text, sizeof(void*));
			parameter+= sizeof(void*);
			type = PARAMETER_TYPE_STRING;
			type_p = &type;
			memcpy(parameter, &type_p, sizeof(void*));
			
			if(ud->parameterNamePtr != NULL && ud->text != NULL){
#if defined(SYSDEF_PARSER_ON_HOST)
				ret = cmsXml_setParameter( pdmCB, ud->currentOffset, 1, tempParameterPtr );
#else
				ret = cmsXml_setParameter(pdmCB, ud->configCurrent->object,1, tempParameterPtr);
#endif
			}
			free(tempParameterPtr);
			free(ud->parameterNamePtr);
			ud->parameterNamePtr=NULL;
			if(ret == CMS_NOK)
			{
				ud->state=StateError;
				errorflag = CMS_NOK;
				break;
			}
		}

		/*if predef.xml has node i, copy i's parameter values to all index childs*/
		attr = NTOHL(ud->configCurrent->attributes);
		tmpName=cmsXmlGetObjRealAddr(pdmCB, NTOHDL(ud->configCurrent->name));
		if((attr & ATTR_INDEXCHILD)&&(stackNode->parameterFlag == 0)&&((tmpName != NULL)&&(*tmpName == 'i')))
		{	
#if 0
			childCount = NTOHL(ud->configCurrent->sibling.child_count);
			while (childCount > 0){
				cmsXml_copyObjectNodeToNode(pdmCB, ud->configCurrent, ud->configCurrent + childCount, 0);
				childCount--;
			}
#endif
		}
		
		if(stackNode->parameterFlag == 0){
#if defined(SYSDEF_PARSER_ON_HOST)
			/* if currentIA is not 0, get this object offset before assign new value. */
			depth = cmsXmlGetIADepth( ud->currentIA );
			if ( ( *name == 'i' ) && atoi( name + 1 ) )
			{
				tmpIA = cmsXmlSetIAValue( ud->currentIA, depth, 0 );
				tmpIA = cmsXmlSetIAValue( tmpIA, IA_DEPTHNUM, depth - 1 );
				ud->currentIA = tmpIA;
			}
#endif
			ud->nodeToParaFlag = 0;
			if(ud->parentList && ud->parentList->next!=NULL)
				ud->configCurrent = ud->parentList->next->node;

			if(ud->parentList != NULL){
				if(ud->parentList->next != NULL)
					tempParentList = ud->parentList->next;
				free(ud->parentList);
				ud->parentList = NULL;
				ud->parentList=tempParentList;
			}
		}
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->textlen=0;
		ud->contentFlag=0;
		break;
	}
	/* This if statement should never be true. The xml lib has internal
	 * checking for this */
	if( stricmp(name, (const char*) stackNode->name))
	{
		CMS_LOG(LL_ERROR, "Closing nodes don't match up name:%s, stackNode->name:%s\n\r", name, stackNode->name);
		ud->state=StateError;
		errorflag = CMS_NOK;
		return;
	}
	NODE_DEL(ud->tagStack, stackNode);
	ud->state=stackNode->prevState;
	NODE_ADD(tagPool, stackNode);
	return;
}

/*
	Description: 
		function used to handle xml content.
	Parameters:
		udRaw: xml parser expat will give this user data pointer.
		ch: content pointer.
		len: content length.
	return:
	
*/
static void cmsXml_contentHandle(void *udRaw, const char *ch, int len)
{
	userData_t	*ud=udRaw;
#ifdef SYSDEF_PARSER_ON_HOST        
    int i, trueContent = 0;
#endif

	if(ud->state == StateNodeNotExist)
	{
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		return;
	}
	
	if(ud->tagStack->parameterFlag != 1)
		return;
	
#if 0	
	if(ud->text != NULL)
	{
		free(ud->text);
		ud->text=NULL;
	}
	ud->text=malloc(len+1);
	memcpy(ud->text, ch, len);
	ud->text[len]='\0';
	ud->textlen=len+1;
#else /*ud->text not NULL is for specfic char, such as &amp, &gt*/
	if(ud->text != NULL)
	{	
		ud->text = realloc(ud->text, ud->textlen+len);
		memcpy(ud->text+ud->textlen-1, ch, len);
		ud->textlen += len;
		ud->text[ud->textlen-1] = '\0';
	}else{
		free(ud->text);
		ud->text=NULL;
		ud->text=malloc(len+1);
		memcpy(ud->text, ch, len);
		ud->text[len]='\0';
		ud->textlen=len+1;
	}
#endif


#ifdef SYSDEF_PARSER_ON_HOST        
	for (i = 0; i < len; i++)
	{
		if (ud->text[i] != 0x20)//check parameter value is space or not 
		{
			trueContent = 1;
			break;
		}
	}
	if (trueContent != 1) // parameter value is empty
	{
		ud->text[0] = '\0';
		ud->textlen=1;
	}
#endif
	//if(ud->textlen)
		//CMS_LOG(LL_DEBUG,"ud->textlen=%d\n\r",ud->textlen);
	return;
}

/*
	Description: 
		function used to load rom to ram.
	Parameters:
		xmlShmCb: xmlContrlBlock
		filename: xml file path.
	return:
		0: CMS_OK
		-1: error
	
*/
int cmsXml_loadRomToRam(cmsXmlCb_t	*xmlShmCb, const char *filename)
{
	userData_t	ud;
	int		retval;
	char	buf[CMS_PDM_MAX_MESSAGE_LEN] = {0};
#ifndef SYSDEF_PARSER_ON_HOST
	char decConfigPath[64] = {0};
	char cmdStr[128] = {0};
#endif
	int		done;
	int		iBuf = 0;
	int 	parseFirstLine = 1;
	char	*pBuf = NULL;
//#if !defined(SYSDEF_PARSER_ON_HOST)
	//char    xmlData[1024] = {0};
//#endif
	FILE 	*file = NULL;
	int i;
	struct stat stat_buf;
#ifndef SYSDEF_PARSER_ON_HOST
	char cmsLogStr[256] = {0};
#endif
	CMS_LOG(LL_FLOOD, "filename:%s", filename);
	
	errorflag = CMS_OK;//reset errorFlag valuie
	
	if(access(filename, F_OK) == -1){
		CMS_LOG(LL_ERROR, "file %s is not exist!", filename);
#ifndef SYSDEF_PARSER_ON_HOST
		memset(cmsLogStr, 0, sizeof(cmsLogStr));
		sprintf(cmsLogStr, "file %s is not exist!\n", filename);
		cms_log_record(cmsLogStr);
#endif
		return CMS_NOK;
	}
	
	memset(&stat_buf, 0, sizeof(struct stat));
	if(stat(filename, &stat_buf) == 0){
		if(stat_buf.st_size == 0){
			CMS_LOG(LL_ERROR, "size of %s is 0", filename);
		#ifndef SYSDEF_PARSER_ON_HOST
			memset(cmsLogStr, 0, sizeof(cmsLogStr));
			sprintf(cmsLogStr,  "size of %s is 0\n\r", filename);
			cms_log_record(cmsLogStr);
		#endif
			return CMS_NOK;
		}
	}

#ifndef SYSDEF_PARSER_ON_HOST
	/*if(strcmp(filename, CMS_CUR_FILE_ENC) == 0){
		ret = cmsXml_checkCurConfigCRC();
		 if(ret == CMS_POK){
			if(access(CMS_BACKUP_CONFIG_FILE, F_OK) != 0){
				CMS_LOG(LL_ERROR, "first time load to bakcp partition version, now load %s again.\n", filename);
				ret = CMS_OK;
			}else{
				ret = CMS_NOK;
			}
		}
		if(ret == CMS_NOK){
			CMS_LOG(LL_ERROR, "config file %s, check sum check fail!!!\n", filename);
			return ret;
		}
	}*/
	
	/*pre & backup partition is not encoded, so just parse*/
	if(strcmp(filename, CMS_BACKUP_CONFIG_FILE) == 0 ||
		strcmp(filename, CMS_PRE_CONFIG_FILE) == 0 ||
		strcmp(filename, CUR_XML_PATH"/config.pre.xml") == 0){
		strcpy(decConfigPath,filename);
	}else{
		strcpy(decConfigPath,  "/tmp/config.dec.xml");
		if(cmsXml_openSSL_Dec(filename, decConfigPath) == CMS_NOK){
			CMS_LOG(LL_ERROR, "dec %s fail.", filename);
			sprintf(cmdStr, "rm %s", decConfigPath);
			cms_do_cmd(cmdStr);
			memset(cmsLogStr, 0, sizeof(cmsLogStr));
			sprintf(cmsLogStr,  "decypt %s fail.\n", filename);
			cms_log_record(cmsLogStr);
			return CMS_NOK;
		}
		sprintf(cmdStr, "rm %s", decConfigPath);
	}
#endif

#ifndef SYSDEF_PARSER_ON_HOST
	file = fopen(decConfigPath, "r");
	if(!file){
		CMS_LOG(LL_ERROR, "File %s not found", decConfigPath);
		memset(cmsLogStr, 0, sizeof(cmsLogStr));
		sprintf(cmsLogStr,  "File %s not found\n\r", decConfigPath);
		cms_log_record(cmsLogStr);
		cms_do_cmd(cmdStr);
		return CMS_NOK;
	}
#else
	file = fopen(filename, "r");
	if(!file){
		CMS_LOG(LL_ERROR, "File %s not found", filename);
		return CMS_NOK;
	}
#endif
#if 0//!defined(SYSDEF_PARSER_ON_HOST)
	else{
		if(fgets(xmlData, 1024, file) != NULL){
			if(strstr(xmlData,"xml version") && strstr(xmlData, "encoding") && strstr(xmlData, "utf-8")){
				CMS_LOG(LL_FLOOD, "check ok\n");
			}else{
				CMS_LOG(LL_ERROR, "File is incomplete!!!\n\r");
				fclose(file);
				return CMS_NOK;
			}
		}else{
			CMS_LOG(LL_ERROR, "get file data fail!!!\n\r");
			fclose(file);
			return CMS_NOK;
		}		
	}
#endif
	
#if 0 //def CMS_XML_PARSE_PHASE_1
#ifdef SYSDEF_PARSER_ON_HOST
	fCurrent = Xml_Read_File(FILTER_PATH);
	if( fCurrent != 0 ) 
	{
		rootFilter = fCurrent;
		filterXmlFlag = 1;
	}
	/* If doesn't exist filter.xml or emptied filter.xml , don't do CMS_XML_PARSE_PHASE_1. */
#endif
#endif
	pdmCB = xmlShmCb;
	parser = XML_ParserCreate(0);// specifies a character encoding to use for the document
	XML_SetUserData(parser, &ud);// This sets the user data pointer that gets passed to handlers.
	XML_SetElementHandler(parser, cms_XmlTagStart, cmsXml_TagEnd);//Set handlers for start and end tags.
	XML_SetCharacterDataHandler(parser, cmsXml_contentHandle);// Set a text handler. 
	cmsXml_UserDataInit(&ud);
	do
	{
		size_t len = fread(buf, 1, sizeof(buf), file);
		done = len < sizeof(buf);
		if(!done)
		{
			i = 0;
			while(buf[CMS_PDM_MAX_MESSAGE_LEN-1-i] != '>')
			{
				i++;
			}
			if(i > 0)
			{
				fseek(file, -i, SEEK_CUR);
				len = len - i;
			}
		}
		pBuf = &buf[0];
		if(parseFirstLine){
			/*
			UTF-8 Byte Order Mark (BOM): EF BB BF.
			Currently, expat does not recognize these bytes but it is a standard.
			Some programs will add BOM to indicate endian format in the first line.
			Please reference this page:
			http://www.w3.org/International/questions/qa-utf8-bom

			To solve this issue, we parse config.xml from first '<'.
			*/
			for(iBuf= 0; iBuf < len; iBuf++){
				if(buf[iBuf] == '<'){
					pBuf = &buf[iBuf];
					len -= iBuf;
					break;
				}
			}
			parseFirstLine = 0;
		}
		retval = XML_Parse(parser, pBuf, len, done);
		if(!retval)
		{
		#ifndef SYSDEF_PARSER_ON_HOST
			CMS_LOG(LL_ERROR, "Error parsing file %s: %s at line %d, pBuf %s.",
				decConfigPath, XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser), pBuf == NULL ? "NULL" : pBuf);
			memset(cmdStr, 0, sizeof(cmdStr));
			snprintf(cmdStr, sizeof(cmdStr) - 1, "cp -f %s %s/config.current.errBak", CMS_CUR_FILE_ENC, CUR_XML_PATH);
			cms_do_cmd(cmdStr);


			memset(cmsLogStr, 0, sizeof(cmsLogStr));
			sprintf(cmsLogStr,  "Error parsing file %s: %s at line %d",
				decConfigPath, XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser));
			cms_log_record(cmsLogStr);
		#else
			CMS_LOG(LL_ERROR, "Error parsing file %s: %s at line %d",
				filename, XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser));
		#endif
			break;
		} 	
	} while(!done);
	XML_ParserFree(parser);
	fclose(file);
#ifndef SYSDEF_PARSER_ON_HOST
	cms_do_cmd(cmdStr);
#endif
	
	if(!retval || errorflag == CMS_NOK){
	#ifndef SYSDEF_PARSER_ON_HOST
		memset(cmsLogStr, 0, sizeof(cmsLogStr));
		sprintf(cmsLogStr,  "Loading %s fail.",filename);
		cms_log_record(cmsLogStr);
	#endif
		return CMS_NOK;
	}

	return CMS_OK;
}

/*
	Description: 
		function used to load rom to ram.
	Parameters:
		xmlShmCb:xmlContrlBlock
		filename: xml file path.
	return:
		0: CMS_OK
		-1: error
	
*/
int cmsXml_loadPredefSettingToRam(cmsXmlCb_t *xmlShmCb, const char *filename)
{
	userData_t	ud;
	int		retval;
	char	buf[CMS_PDM_MAX_MESSAGE_LEN] = {0};
	int		done;
	FILE 	*file = NULL;
	int 	i;

	CMS_LOG(LL_FLOOD, "filename:%s\n", filename);

	if(xmlShmCb == NULL || filename == NULL){
		CMS_LOG(LL_ERROR, "func parameter is NULL.\n");
		return CMS_NOK;
	}
		
	file = fopen(filename, "r");
	if(!file){
		CMS_LOG(LL_ERROR, "File not found\n\r");
		return CMS_NOK;
	}
	pdmCB = xmlShmCb;
	parser = XML_ParserCreate(0);// specifies a character encoding to use for the document
	XML_SetUserData(parser, &ud);// This sets the user data pointer that gets passed to handlers.
	XML_SetElementHandler(parser, cmsXml_PredefTagStart, cmsXml_PredefTagEnd);//Set handlers for start and end tags.
	XML_SetCharacterDataHandler(parser, cmsXml_contentHandle);// Set a text handler. 
	cmsXml_UserDataInit(&ud);
	do
	{
		size_t len = fread(buf, 1, sizeof(buf), file);
		done = len < sizeof(buf);
		if(!done)
		{
			i = 0;
			while(buf[CMS_PDM_MAX_MESSAGE_LEN-1-i] != '>')
			{
				i++;
			}
			if(i > 0)
			{
				fseek(file, -i, SEEK_CUR);
				len = len - i;
			}
		}
		retval = XML_Parse(parser, buf, len, done);
		if(!retval)
		{
			CMS_LOG(LL_ERROR, "Error parsing file %s: %s at line %d\n\r",
			filename, XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser));
			break;
		} 	
	} while(!done);
	XML_ParserFree(parser);
	fclose(file);
	if(!retval || errorflag == CMS_NOK)
		return CMS_NOK;
	
	return CMS_OK;
}

#ifdef SYSDEF_PARSER_ON_HOST
static void cmsXml_checkXmlStart(void *udRaw, const char *name, const char **attrs)
{
	userData_t	*ud=udRaw;
	tagNode_t	*stackNode=NULL;
	int skip =0;
	objectNode_t *node = NULL, *tmpCurrent = NULL;
	uint32_t flags;
	parentList_t *parentList;
	int		pushstack=1;
	attrList_t *attrList=NULL;
	uint32_t attr;
	int depth = 0;
	uint64_t tmpIA = 0;

	if(ud->state == StateNodeNotExist)
	{
		nodeNum++;
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		return;
	}
	/* Get a tag for this element */
	stackNode=tagPool;
	if(!stackNode){
		/* pool empty, get new tag_node */
		stackNode=(tagNode_t *)malloc(sizeof(tagNode_t));
		if(!stackNode){
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "no memory for stackNode.\n\r");
			return;
		}
		memset(stackNode, 0, sizeof(tagNode_t));
	}
	else
	{
		NODE_DEL(tagPool,stackNode);
	}
	
	if(strlen(name) > CMS_PDM_MAX_NODE_NAME_LEN)
	{
		ud->state=StateError;
		CMS_LOG(LL_ERROR, "XML error at line %d: Tag name is too long.\n\r", XML_GetCurrentLineNumber(parser));
		goto error_handle;
	}
	
	stackNode->prevState=ud->state;
	strcpy(stackNode->name, name);
	switch(ud->state){
	case StateSetting:	
		/* Add all the attributes */
		attrList=(struct attrList_s *)malloc(sizeof(struct attrList_s));
		memset(attrList, 0, sizeof(struct attrList_s));
		if(cms_GetAttrValue2(attrs, attrList)!=0){
			goto error_handle;
		}
		if(attrList->paraFlag)//parameter
		{	
			/*check the parameter is exist or not*/
			parameterValue_t *paraValue = NULL;
			char *parameter[1];
			char paramName[CMS_PDM_MAX_NODE_NAME_LEN];
			strcpy(paramName, name);
			parameter[0] = paramName;
			paraValue = cmsXml_getParameter(pdmCB, ud->currentOffset, 1, parameter);
			if(paraValue == NULL){
				CMS_LOG(LL_ERROR, "can found paramter %s, error at line %d\n",  (char *)name, XML_GetCurrentLineNumber(parser));
				ud->state=StateError;
				goto error_handle;
			}
			free(paraValue);

			/*set parameter attr*/
			flags = cmsXml_getParameterAttr( pdmCB, ud->currentOffset, (char *)name );
			if((flags & PARAMETER_ATTR_CONFIG) != PARAMETER_ATTR_CONFIG){
				CMS_LOG(LL_ERROR, "nonconfiged paramter %s, error at line %d\n",  (char *)name, XML_GetCurrentLineNumber(parser));
				ud->state=StateError;
				goto error_handle;
			}
			
			if(NTOHL(attrList->attrValue) & PARAMETER_ATTR_ACTIVENOTIFY)
				flags |= PARAMETER_ATTR_ACTIVENOTIFY;
			else if(NTOHL(attrList->attrValue) & PARAMETER_ATTR_PASSIVENOTIFY)
				flags |= PARAMETER_ATTR_PASSIVENOTIFY;
			else
			{
				flags &=~ PARAMETER_ATTR_ACTIVENOTIFY;
				flags &=~ PARAMETER_ATTR_PASSIVENOTIFY;
			}

			cmsXml_setParameterAttr( pdmCB, ud->currentOffset, (char *)name, flags, 1 );
			
			ud->parameterNamePtr=malloc(CMS_PDM_MAX_NODE_NAME_LEN);
			strcpy(ud->parameterNamePtr, name);
			stackNode->parameterFlag = 1;
			ud->checkContentFlag = 1;
		}else{
			node = (objectNode_t *)cmsXmlGetObjRealAddr(pdmCB, NTOHDL(ud->parentList->node->child));
			if (((NTOHL(node->attributes) & ATTR_INDEXCHILD) == ATTR_INDEXCHILD)&&(*(name+1) != '\0')){
				skip = 1;
			}

			/* change to find prototype and check this index child node is existed or not. */
			/* if this node not existed, create it and set the value. */
			if ( skip == 1 )
			{
				/* get prototype node. */
				tmpCurrent = cmsXml_SearchChildNode( pdmCB, node, "i", NULL );
				if(tmpCurrent==NULL){
					ud->state=StateError;
					nodeNum++;
					CMS_LOG(LL_ERROR, "No proto node of node %s, cmsXml_SearchChildNode failed!\n\r", name);
					goto error_handle;
				}
				if(atoi(name+1) > tmpCurrent->sibling.child_count){
					ud->state=StateError;
					CMS_LOG(LL_ERROR, "index num(%s) excced the max num(%d), error at line %d!\n\r", name,  tmpCurrent->sibling.child_count,  XML_GetCurrentLineNumber(parser));
					goto error_handle;
				}
				tmpIA = NTOHLL( cmsXmlGetPreObjIA( pdmCB, NTOHL( tmpCurrent->object ) ) );
				depth = cmsXmlGetIADepth( tmpIA );

				/* setup IA by depth and index number. */
				if ( atoi( name + 1 ) )
				{
					tmpIA = cmsXmlSetIAValue( ud->currentIA, depth, atoi( name + 1 ) );
					tmpIA = cmsXmlSetIAValue( tmpIA, IA_DEPTHNUM, depth );
				}
				ud->currentIA = tmpIA;

				/* test this index child object is existed or not. if not existed, create this index child object. */
				/* input offset is network type; output offset is network type. */
				ud->currentOffset = cmsXmlAddObjectWithAssignIA( pdmCB, tmpCurrent->object, ud->currentIA );
			}
			else
			{
				tmpCurrent = cmsXml_SearchChildNode( pdmCB, node, (char *)name, NULL );
				if(tmpCurrent==NULL){
					ud->state=StateError;
					nodeNum++;
					CMS_LOG(LL_ERROR, "No node %s at line %d, cmsXml_SearchChildNode failed!\n\r", name, XML_GetCurrentLineNumber(parser));
					goto error_handle;
				}
				ud->currentOffset = tmpCurrent->object;

				/* point to prototype node, IA should not have value. */
				if ( ( *name == 'i' ) && ( strlen( name ) == 1 ) && ud->currentIA )
				{
					ud->state = StateError;
					CMS_LOG(LL_ERROR, "cmsXml_PredefTagStart \"%s\" fail.\n\r", name );
					break;
				}
				else if ( ud->currentIA && ( NTOHL( tmpCurrent->attributes ) & ATTR_OBJECTNODE ) )
				{
					/* test this index child object is existed or not. if not existed, create this index child object. */
					ud->currentOffset = cmsXmlAddObjectWithAssignIA( pdmCB, tmpCurrent->object, ud->currentIA );
				}
			}

			/*if the ACTIVENODE is set for the node, mark the node ALWAYSACTIVE for tr069*/
			if ((attrList->attrValue & ATTR_ALWAYSACTIVE) == ATTR_ALWAYSACTIVE){
				attr = NTOHL( tmpCurrent->attributes ) | ATTR_NODECONFIGURED;
				tmpCurrent->attributes = HTONL( attr );
				attr |= ATTR_ALWAYSACTIVE;
				cmsXml_SetPreObjAttr( pdmCB, NTOHL( ud->currentOffset ), HTONL( attr ) );
			}
			ud->configCurrent = tmpCurrent;
			stackNode->parameterFlag = 0;
			ud->checkContentFlag = 0;
		}	
		if(attrList->paraFlag == 0)
		{
			parentList=(struct parentList_s *)malloc(sizeof(struct parentList_s));
			parentList->node = ud->configCurrent;
			parentList->next=ud->parentList;	
			ud->parentList=parentList;		
		}
		/* Setup the content pointers */
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->contentFlag=1;
		free(attrList);
		break;
	case StateDone:
	case StateError:
		pushstack=0;
		errorflag = CMS_NOK;
		goto error_handle;
	case StateUnknown:
		break;
	case StateStart:
		if(!(ud->configHead = 	cmsXml_SearchChildNode(pdmCB, pdmCB->rootNode, (char *)name,NULL)))
		{
			ud->state=StateError;
			CMS_LOG(LL_ERROR, "cmsXml_SearchChildNode \"%s\" fail.\n\r", name);
			break;
		}
		ud->configCurrent= ud->configHead;
		ud->currentOffset = ud->configCurrent->object;
		
		stackNode->parameterFlag = 0;
		parentList=(struct parentList_s *)malloc(sizeof(struct parentList_s));
		parentList->node = ud->configCurrent;
		parentList->next=ud->parentList;	
		ud->parentList=parentList;
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->contentFlag=1;
		ud->state=StateSetting;
		break;
	default:
		ud->state=StateError;
		pushstack=0;
		break;
	}

	if(pushstack)
	{
		NODE_ADD(ud->tagStack, stackNode);
	}
	else
	{
		NODE_ADD(tagPool, stackNode);
	}
	return;
error_handle:
	if (attrList)
		free(attrList);
	return;
}

static void cmsXml_checkXmlEnd(void *udRaw, const char *name)
{
	userData_t *ud = udRaw;
	tagNode_t *stackNode;
	uint32_t type = PARAMETER_TYPE_STRING;
	char *param_pp[3];
	int ret = 0;
	parentList_t *tempParentList = NULL;
	int depth = 0;
	uint64_t tmpIA = 0;

	if(ud->state == StateNodeNotExist)
	{
		nodeNum--;
		CMS_LOG(LL_ERROR, "Node not found.\n\r");
		if(nodeNum == 0)
			ud->state=StateSetting;
		return;
	}
	stackNode=ud->tagStack;
	if(!stackNode){
		CMS_LOG(LL_ERROR, "No tag node.\n\r");
		ud->state=StateError;
		errorflag = CMS_NOK;
		return;
	}
	switch(ud->state)
	{
	case StateError:
		return;
	case StateSetting:
		if(!ud->configHead)
		{
			CMS_LOG(LL_ERROR, "Lost head node.\n\r");
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}
		if(!ud->configCurrent)
		{
			CMS_LOG(LL_ERROR, "Lost current node.\n\r");
			ud->state=StateError;
			errorflag = CMS_NOK;
			break;
		}

		if(ud->contentFlag != 0 && ud->parameterNamePtr != NULL && ud->text != NULL){
			param_pp[0] = ud->parameterNamePtr;
			param_pp[1] = ud->text;
			param_pp[2] = (char *)&type;

			ret = cmsXml_setParameter( pdmCB, ud->currentOffset, 1, param_pp);

			free(ud->parameterNamePtr);
			ud->parameterNamePtr=NULL;
			if(ret == CMS_NOK)
			{
				ud->state=StateError;
				errorflag = CMS_NOK;
				CMS_LOG(LL_ERROR, "set parameter %s fail, value is %s, error at line %d!\n\r", name, ud->text, XML_GetCurrentLineNumber(parser));
				break;
			}
		}
		
		if(stackNode->parameterFlag == 0){
			/* if currentIA is not 0, get this object offset before assign new value. */
			depth = cmsXmlGetIADepth( ud->currentIA );
			if ( ( *name == 'i' ) && atoi( name + 1 ) )
			{
				tmpIA = cmsXmlSetIAValue( ud->currentIA, depth, 0 );
				tmpIA = cmsXmlSetIAValue( tmpIA, IA_DEPTHNUM, depth - 1 );
				ud->currentIA = tmpIA;
			}

			ud->nodeToParaFlag = 0;
			if(ud->parentList && ud->parentList->next!=NULL)
				ud->configCurrent = ud->parentList->next->node;

			if(ud->parentList != NULL){
				if(ud->parentList->next != NULL)
					tempParentList = ud->parentList->next;
				free(ud->parentList);
				ud->parentList = NULL;
				ud->parentList=tempParentList;
			}
		}
		if(ud->text != NULL)
		{
			free(ud->text);
			ud->text=NULL;
		}
		ud->textlen=0;
		ud->contentFlag=0;
		break;
	}
	/* This if statement should never be true. The xml lib has internal
	 * checking for this */
	if( stricmp(name, (const char*) stackNode->name))
	{
		CMS_LOG(LL_ERROR, "Closing nodes don't match up name:%s, stackNode->name:%s\n\r", name, stackNode->name);
		ud->state=StateError;
		errorflag = CMS_NOK;
		return;
	}
	NODE_DEL(ud->tagStack, stackNode);
	ud->state=stackNode->prevState;
	NODE_ADD(tagPool, stackNode);
	return;
}


int cmsXml_checkXml(cmsXmlCb_t	*xmlShmCb, const char *filename)
{
	userData_t	ud;
	int		retval;
	char	buf[CMS_PDM_MAX_MESSAGE_LEN] = {0};
	int		done;
	int		iBuf = 0;
	int 	parseFirstLine = 1;
	char	*pBuf = NULL;
	char    xmlData[1024] = {0};
	FILE 	*file = NULL;
	int i;
	struct stat stat_buf;
	CMS_LOG(LL_FLOOD, "filename:%s\n", filename);
	
	memset(&stat_buf, 0, sizeof(struct stat));
	if(stat(filename, &stat_buf) == 0){
		if(stat_buf.st_size == 0){
			CMS_LOG(LL_ERROR, "size of %s is 0\n\r", filename);
			return CMS_NOK;
		}
	}

	file = fopen(filename, "r");
	if(!file){
		CMS_LOG(LL_ERROR, "File not found\n\r");
		return CMS_NOK;
	}else{
		if(fgets(xmlData, 1024, file) != NULL){
			if(strstr(xmlData,"xml version") && strstr(xmlData, "encoding") && strstr(xmlData, "utf-8")){
				CMS_LOG(LL_FLOOD, "check ok\n");
			}else{
				CMS_LOG(LL_ERROR, "File is incomplete, first line %s!!!\n\r", xmlData);
				fclose(file);
				return CMS_NOK;
			}
		}else{
			CMS_LOG(LL_ERROR, "get file data fail!!!\n\r");
			fclose(file);
			return CMS_NOK;
		}
		
	}

	pdmCB = xmlShmCb;
	parser = XML_ParserCreate(0);// specifies a character encoding to use for the document
	XML_SetUserData(parser, &ud);// This sets the user data pointer that gets passed to handlers.
	XML_SetElementHandler(parser, cmsXml_checkXmlStart, cmsXml_checkXmlEnd);//Set handlers for start and end tags.
	XML_SetCharacterDataHandler(parser, cmsXml_contentHandle);// Set a text handler. 
	cmsXml_UserDataInit(&ud);
	do
	{
		size_t len = fread(buf, 1, sizeof(buf), file);
		done = len < sizeof(buf);
		if(!done)
		{
			i = 0;
			while(buf[CMS_PDM_MAX_MESSAGE_LEN-1-i] != '>')
			{
				i++;
			}
			if(i > 0)
			{
				fseek(file, -i, SEEK_CUR);
				len = len - i;
			}
		}
		pBuf = &buf[0];
		if(parseFirstLine){
			/*
			UTF-8 Byte Order Mark (BOM): EF BB BF.
			Currently, expat does not recognize these bytes but it is a standard.
			Some programs will add BOM to indicate endian format in the first line.
			Please reference this page:
			http://www.w3.org/International/questions/qa-utf8-bom

			To solve this issue, we parse config.xml from first '<'.
			*/
			for(iBuf= 0; iBuf < len; iBuf++){
				if(buf[iBuf] == '<'){
					pBuf = &buf[iBuf];
					len -= iBuf;
					break;
				}
			}
			parseFirstLine = 0;
		}
		retval = XML_Parse(parser, pBuf, len, done);
		if(!retval)
		{
			CMS_LOG(LL_ERROR, "Error parsing file %s: %s at line %d\n\r",
			filename, XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser));
			break;
		} 	
	} while(!done);
	XML_ParserFree(parser);
	fclose(file);

	if(!retval || errorflag == CMS_NOK)
		return CMS_NOK;

	return CMS_OK;
}
#endif

#if defined(SYSDEF_PARSER_ON_HOST) /* compile time. */
#define TYP_INIT 0
#define TYP_SMLE 1
#define TYP_BIGE 2
 
unsigned long long HTONLL( unsigned long long src )
{
	static int typ = TYP_INIT;
	unsigned char c;
	union {
		unsigned long long ull;
		unsigned char c[ 8 ];
	} x;

	if ( typ == TYP_INIT )
	{
		x.ull = 0x01;
		typ = (x.c[7] == 0x01ULL) ? TYP_BIGE : TYP_SMLE;
	}
	if ( typ == TYP_BIGE )
		return src;

	x.ull = src;
	c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c;
	c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c;
	c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c;
	c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c;

	return x.ull;
}

unsigned long long NTOHLL( unsigned long long src )
{
	unsigned long long rval;
	unsigned char *data = (unsigned char *)&rval;

	data[0] = src >> 56;
	data[1] = src >> 48;
	data[2] = src >> 40;
	data[3] = src >> 32;
	data[4] = src >> 24;
	data[5] = src >> 16;
	data[6] = src >> 8;
	data[7] = src >> 0;

	return rval;
}

void printIAArray( uint64_t value )
{
	int i = 0;

	for ( i = 1; i < 8; i++ )
		CMS_LOG(LL_FLOOD, "%d, ", cmsXmlGetIAInfo( value, i ) );

	CMS_LOG(LL_FLOOD, "%d\n", cmsXmlGetIAInfo( value, IA_DEPTHNUM ) );
}

uint64_t cmsXmlSetIAValue( uint64_t originalValue, int index, uint64_t setValue )
{
	uint64_t testFF = 0xFF;
	return ( originalValue&(~(testFF<<((8-index)*8)))) | (setValue<<((8-index)*8) );
}

/* 0 is different, 1 is the same. */
int compareIAByDepth( uint64_t a, uint64_t b, uint8_t depth )
{
	int i = 1;

	for ( i = 1; i <= depth; i++ )
	{
		if ( cmsXmlGetIAInfo( a, i ) != cmsXmlGetIAInfo( b, i ) )
		{
			return 0;
		}
	}
	return 1;
}

void cmsXml_SetPreObjIA( cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset, uint64_t valueIA )
{
	uint64_t newValue = valueIA;
	memcpy( ( xmlShmCb->baseaddr + objOffset ) - PREIA_LEN, &newValue, sizeof( uint64_t ) );
}

void cmsXml_SetPreObjNext( cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset, cmsoffset_t valueOffset )
{
	cmsoffset_t newValue = valueOffset;
	memcpy( ( xmlShmCb->baseaddr + objOffset ) - PRENEXT_LEN, &newValue, sizeof( cmsoffset_t ) );
}

void cmsXml_SetPreObjAttr( cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset, uint32_t valueAttr )
{
	uint32_t newValue = valueAttr;
	memcpy( ( xmlShmCb->baseaddr + objOffset ) - PREATTR_LEN, &newValue, sizeof( uint32_t ) );
}

/* create new preobj + object from src node and write offset to preobj of src node, return the real addr of this object. */
/* IA: host type, offset: network , return offset is network type.*/
cmsoffset_t cmsXmlAddObjectWithAssignIA( cmsXmlCb_t *pdmCB, cmsoffset_t offset, uint64_t IA )
{
	char *srcObj, *dstHead;
	objectNode_t *srcNode;
	uint64_t getIAValue = 0;
	cmsoffset_t srcOffset = 0, getOffset = 0, finalOffset = 0, prevOffset = 0, newOffset = 0;
	int depth = 0, insert = 0, num = 0;
	uint32_t attr = 0;

	prevOffset = finalOffset = srcOffset = offset; // this offset is network type.
	// IA is network type.
	depth = cmsXmlGetIADepth( IA );
	num = cmsXmlGetIAInfo( IA, depth );
	//CMS_LOG(LL_DEBUG, "num=%d, depth=%d, srcOffset=%lu\n", num, depth, NTOHL( srcOffset ) );

	/* figure out what position this new index object node should be located in. */
	getOffset = cmsXmlGetPreObjNext( pdmCB, NTOHL( srcOffset ) ); // getOffset is network type.
	//CMS_LOG(LL_DEBUG, "getOffset=%lu\n", getOffset );
	while( getOffset ) /* continue to check next offset. */
	{
		getIAValue = cmsXmlGetPreObjIA( pdmCB, NTOHL( getOffset ) );
		getIAValue = NTOHLL( getIAValue );
		//CMS_LOG(LL_DEBUG, "getIAValue= " );
		//printIAArray( getIAValue );
		if ( compareIAByDepth( IA, getIAValue, depth ) )
		{
			//CMS_LOG(LL_DEBUG, "this num %d is occupid.\n", num );
			return getOffset;
		}
		else if ( compareIAByDepth( IA, getIAValue, depth - 1 ) && cmsXmlGetIAInfo( getIAValue, depth ) > num ) /* this new index object should be inserted between prevOffset and finalOffset. */
		{
			insert = 1;
			prevOffset = finalOffset;
			finalOffset = getOffset;
			//CMS_LOG(LL_DEBUG, "larger number is occupid, we need to insert new index object node before this node.\n" );
			break;
		}
		prevOffset = finalOffset;
		finalOffset = getOffset;
		getOffset = cmsXmlGetPreObjNext( pdmCB, NTOHL( finalOffset ) );
	}

	/* find available space to store new preobj+ object. */
	dstHead = cmsXmlGetObjRealAddr( pdmCB, getRdmTotalSize() );
	//CMS_LOG(LL_DEBUG, "dstHead=%p, getRdmTotalSize()=%lu\n", dstHead, getRdmTotalSize() );

	srcNode = (objectNode_t *)cmsXmlGetObjRealAddr( pdmCB, NTOHL( cmsXmlGetPreObjNode( pdmCB, NTOHL( srcOffset ) ) ) );
	//CMS_LOG(LL_DEBUG, "srcNode->object_size=%lu\n", NTOHL( srcNode->object_size ) );

	srcObj = cmsXmlGetObjRealAddr( pdmCB, NTOHL( srcOffset ) );
	memcpy( dstHead, srcObj - PREOBJ_LEN, NTOHL( srcNode->object_size ) + PREOBJ_LEN );

	newOffset = cmsXmlGetPtrOffset( pdmCB, dstHead + PREOBJ_LEN );
	//CMS_LOG(LL_DEBUG, "cmsXmlGetUsedShmSize( xmlShmCb )=%lu, newOffset=%lu\n", cmsXmlGetUsedShmSize( xmlShmCb ), newOffset );
	//CMS_LOG(LL_DEBUG, "rdmGetPreObjNode( newOffset )=%lu, srcOffset=%lu\n", cmsXmlGetPreObjNode( xmlShmCb, newOffset ), rdmGetPreObjNode( xmlShmCb, NTOHL( srcOffset ) ) );
	//CMS_LOG(LL_DEBUG, "newOffset=%lu, prevOffset=%lu, finalOffset=%lu, insert=%d\n", newOffset, prevOffset, finalOffset, insert );

	/* increase used shm size for next time to add new object. */
	addRdmTotalSize( NTOHL( srcNode->object_size ) + PREOBJ_LEN );
	//CMS_LOG(LL_DEBUG, "getRdmTotalSize()=%lu\n", getRdmTotalSize() );

	/* initial: set next to zero for this new index object node. */
	cmsXml_SetPreObjNext( pdmCB, newOffset, HTONL( 0 ) );
	
	/* set offset of new index object to next offset of final object with empty next. */
	if ( insert ) /* this new index object should be inserted between prevOffset and finalOffset. */
	{
		cmsXml_SetPreObjNext( pdmCB, NTOHL( prevOffset ), HTONL( newOffset ) );
		cmsXml_SetPreObjNext( pdmCB, newOffset, finalOffset );
	}
	else /* just write next to finalOffset. */
	{
		cmsXml_SetPreObjNext( pdmCB, NTOHL( finalOffset ), HTONL( newOffset ) );
	}
	//printIAArray( IA );

	/* set attribute to pre-obj. */
	attr = NTOHL( cmsXmlGetPreObjAttr( pdmCB, newOffset ) );
	attr |= ATTR_NODECONFIGURED;
	cmsXml_SetPreObjAttr( pdmCB, newOffset, HTONL( attr ) );

	/* write index number in IA. */
	cmsXml_SetPreObjIA( pdmCB, newOffset, HTONLL( IA ) );

	return HTONL( newOffset );
}
#endif
